summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 09:34:35 +0000
committerdanno@chromium.org <danno@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-23 09:34:35 +0000
commit88616f47602e8a2a16c65ca0a59444e0ce550772 (patch)
tree285cad010b0aee7f2001fe419191cd1ee41a00ee
parent5e0750503a3c9743e1245f1b4c540124a9722ea0 (diff)
downloadchromium_src-88616f47602e8a2a16c65ca0a59444e0ce550772.zip
chromium_src-88616f47602e8a2a16c65ca0a59444e0ce550772.tar.gz
chromium_src-88616f47602e8a2a16c65ca0a59444e0ce550772.tar.bz2
Refactor the windows policy provider to use AsynchronousPolicyProvider.
BUG=66453,65094 TEST=*Policy.* Review URL: http://codereview.chromium.org/6091002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@70040 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/policy/asynchronous_policy_loader.cc84
-rw-r--r--chrome/browser/policy/asynchronous_policy_loader.h38
-rw-r--r--chrome/browser/policy/asynchronous_policy_loader_unittest.cc8
-rw-r--r--chrome/browser/policy/asynchronous_policy_provider_unittest.cc9
-rw-r--r--chrome/browser/policy/configuration_policy_loader_win.cc90
-rw-r--r--chrome/browser/policy/configuration_policy_loader_win.h57
-rw-r--r--chrome/browser/policy/configuration_policy_provider_delegate_win.cc160
-rw-r--r--chrome/browser/policy/configuration_policy_provider_delegate_win.h47
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win.cc284
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win.h95
-rw-r--r--chrome/browser/policy/configuration_policy_provider_win_unittest.cc22
-rw-r--r--chrome/browser/policy/file_based_policy_loader.cc73
-rw-r--r--chrome/browser/policy/file_based_policy_loader.h40
-rw-r--r--chrome/chrome_browser.gypi4
14 files changed, 526 insertions, 485 deletions
diff --git a/chrome/browser/policy/asynchronous_policy_loader.cc b/chrome/browser/policy/asynchronous_policy_loader.cc
index e78c9aa..cf67066 100644
--- a/chrome/browser/policy/asynchronous_policy_loader.cc
+++ b/chrome/browser/policy/asynchronous_policy_loader.cc
@@ -6,21 +6,43 @@
#include "base/message_loop.h"
#include "base/task.h"
+#include "chrome/browser/browser_thread.h"
namespace policy {
AsynchronousPolicyLoader::AsynchronousPolicyLoader(
- AsynchronousPolicyProvider::Delegate* delegate)
+ AsynchronousPolicyProvider::Delegate* delegate,
+ int reload_interval_minutes)
: delegate_(delegate),
provider_(NULL),
- origin_loop_(MessageLoop::current()) {}
+ reload_task_(NULL),
+ reload_interval_(base::TimeDelta::FromMinutes(reload_interval_minutes)),
+ origin_loop_(MessageLoop::current()),
+ stopped_(false) {}
void AsynchronousPolicyLoader::Init() {
policy_.reset(delegate_->Load());
+ // Initialization can happen early when the file thread is not yet available,
+ // but the subclass of the loader must do some of their initialization on the
+ // file thread. Posting to the file thread directly before it is initialized
+ // will cause the task to be forgotten. Instead, post a task to the ui thread
+ // to delay the remainder of initialization until threading is fully
+ // initialized.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &AsynchronousPolicyLoader::InitAfterFileThreadAvailable));
}
void AsynchronousPolicyLoader::Stop() {
- delegate_.reset();
+ if (!stopped_) {
+ stopped_ = true;
+ delegate_.reset();
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &AsynchronousPolicyLoader::StopOnFileThread));
+ }
}
void AsynchronousPolicyLoader::SetProvider(
@@ -57,6 +79,54 @@ void AsynchronousPolicyLoader::Reload() {
}
}
+void AsynchronousPolicyLoader::CancelReloadTask() {
+ if (reload_task_) {
+ // Only check the thread if there's still a reload task. During
+ // destruction of unit tests, the message loop destruction can
+ // call this method when the file thread is no longer around,
+ // but in that case reload_task_ is NULL.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ reload_task_->Cancel();
+ reload_task_ = NULL;
+ }
+}
+
+void AsynchronousPolicyLoader::ScheduleReloadTask(
+ const base::TimeDelta& delay) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ CancelReloadTask();
+
+ reload_task_ =
+ NewRunnableMethod(this, &AsynchronousPolicyLoader::ReloadFromTask);
+ BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, reload_task_,
+ delay.InMilliseconds());
+}
+
+void AsynchronousPolicyLoader::ScheduleFallbackReloadTask() {
+ // As a safeguard in case that the load delegate failed to timely notice a
+ // change in policy, schedule a reload task that'll make us recheck after a
+ // reasonable interval.
+ ScheduleReloadTask(reload_interval_);
+}
+
+void AsynchronousPolicyLoader::ReloadFromTask() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ // Drop the reference to the reload task, since the task might be the only
+ // referrer that keeps us alive, so we should not Cancel() it.
+ reload_task_ = NULL;
+
+ Reload();
+}
+
+void AsynchronousPolicyLoader::InitOnFileThread() {
+}
+
+void AsynchronousPolicyLoader::StopOnFileThread() {
+ CancelReloadTask();
+}
+
void AsynchronousPolicyLoader::PostUpdatePolicyTask(
DictionaryValue* new_policy) {
origin_loop_->PostTask(FROM_HERE, new UpdatePolicyTask(this, new_policy));
@@ -75,4 +145,12 @@ void AsynchronousPolicyLoader::UpdatePolicy(DictionaryValue* new_policy_raw) {
}
}
+void AsynchronousPolicyLoader::InitAfterFileThreadAvailable() {
+ if (!stopped_) {
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this, &AsynchronousPolicyLoader::InitOnFileThread));
+ }
+}
+
} // namespace policy
diff --git a/chrome/browser/policy/asynchronous_policy_loader.h b/chrome/browser/policy/asynchronous_policy_loader.h
index d88cdff..8a5838f 100644
--- a/chrome/browser/policy/asynchronous_policy_loader.h
+++ b/chrome/browser/policy/asynchronous_policy_loader.h
@@ -21,7 +21,8 @@ class AsynchronousPolicyLoader
: public base::RefCountedThreadSafe<AsynchronousPolicyLoader> {
public:
explicit AsynchronousPolicyLoader(
- AsynchronousPolicyProvider::Delegate* delegate);
+ AsynchronousPolicyProvider::Delegate* delegate,
+ int reload_interval_minutes);
// Triggers initial policy load.
virtual void Init();
@@ -55,13 +56,32 @@ class AsynchronousPolicyLoader
return delegate_.get();
}
- AsynchronousPolicyProvider* provider() {
- return provider_;
- }
+ // Performs start operations that must be performed on the file thread.
+ virtual void InitOnFileThread();
+
+ // Performs stop operations that must be performed on the file thread.
+ virtual void StopOnFileThread();
+
+ // Schedules a reload task to run when |delay| expires. Must be called on the
+ // file thread.
+ void ScheduleReloadTask(const base::TimeDelta& delay);
+
+ // Schedules a reload task to run after the number of minutes specified
+ // in |reload_interval_minutes_|. Must be called on the file thread.
+ void ScheduleFallbackReloadTask();
+
+ void CancelReloadTask();
+
+ // Invoked from the reload task on the file thread.
+ void ReloadFromTask();
private:
friend class AsynchronousPolicyLoaderTest;
+ // Finishes loader initialization after the threading system has been fully
+ // intialized.
+ void InitAfterFileThreadAvailable();
+
// Replaces the existing policy to value map with a new one, sending
// notification to the provider if there is a policy change. Must be called on
// |origin_loop_| so that it's safe to call back into the provider, which is
@@ -78,11 +98,21 @@ class AsynchronousPolicyLoader
// called the constructor. See |origin_loop_| below.
AsynchronousPolicyProvider* provider_;
+ // The reload task. Access only on the file thread. Holds a reference to the
+ // currently posted task, so we can cancel and repost it if necessary.
+ CancelableTask* reload_task_;
+
+ // The interval at which a policy reload will be triggered as a fallback.
+ const base::TimeDelta reload_interval_;
+
// The message loop on which this object was constructed. Recorded so that
// it's possible to call back into the non thread safe provider to fire the
// notification.
MessageLoop* origin_loop_;
+ // True if Stop has been called.
+ bool stopped_;
+
DISALLOW_COPY_AND_ASSIGN(AsynchronousPolicyLoader);
};
diff --git a/chrome/browser/policy/asynchronous_policy_loader_unittest.cc b/chrome/browser/policy/asynchronous_policy_loader_unittest.cc
index 4995431..1fc1ee5 100644
--- a/chrome/browser/policy/asynchronous_policy_loader_unittest.cc
+++ b/chrome/browser/policy/asynchronous_policy_loader_unittest.cc
@@ -53,7 +53,7 @@ TEST_F(AsynchronousPolicyLoaderTest, InitialLoad) {
DictionaryValue* template_dict(new DictionaryValue());
EXPECT_CALL(*delegate_, Load()).WillOnce(Return(template_dict));
scoped_refptr<AsynchronousPolicyLoader> loader =
- new AsynchronousPolicyLoader(delegate_.release());
+ new AsynchronousPolicyLoader(delegate_.release(), 10);
loader->Init();
const DictionaryValue* loaded_dict(loader->policy());
EXPECT_TRUE(loaded_dict->Equals(template_dict));
@@ -68,7 +68,7 @@ TEST_F(AsynchronousPolicyLoaderTest, InitialLoadWithFallback) {
EXPECT_CALL(*delegate_, Load()).WillOnce(
CreateSequencedTestDictionary(&dictionary_number));
scoped_refptr<AsynchronousPolicyLoader> loader =
- new AsynchronousPolicyLoader(delegate_.release());
+ new AsynchronousPolicyLoader(delegate_.release(), 10);
loader->Init();
loop_.RunAllPending();
loader->Reload();
@@ -86,7 +86,7 @@ TEST_F(AsynchronousPolicyLoaderTest, Stop) {
ON_CALL(*delegate_, Load()).WillByDefault(CreateTestDictionary());
EXPECT_CALL(*delegate_, Load()).Times(1);
scoped_refptr<AsynchronousPolicyLoader> loader =
- new AsynchronousPolicyLoader(delegate_.release());
+ new AsynchronousPolicyLoader(delegate_.release(), 10);
loader->Init();
loop_.RunAllPending();
loader->Stop();
@@ -118,7 +118,7 @@ TEST_F(AsynchronousPolicyLoaderTest, ProviderNotificationOnPolicyChange) {
EXPECT_CALL(*delegate_, Load()).WillOnce(
CreateSequencedTestDictionary(&dictionary_number_1));
scoped_refptr<AsynchronousPolicyLoader> loader =
- new AsynchronousPolicyLoader(delegate_.release());
+ new AsynchronousPolicyLoader(delegate_.release(), 10);
AsynchronousPolicyProvider provider(NULL, loader);
loop_.RunAllPending();
loader->Reload();
diff --git a/chrome/browser/policy/asynchronous_policy_provider_unittest.cc b/chrome/browser/policy/asynchronous_policy_provider_unittest.cc
index 64306eb..c6aee70 100644
--- a/chrome/browser/policy/asynchronous_policy_provider_unittest.cc
+++ b/chrome/browser/policy/asynchronous_policy_provider_unittest.cc
@@ -17,6 +17,7 @@ using ::testing::Return;
namespace policy {
+// Creating the provider should provide initial policy.
TEST_F(AsynchronousPolicyTestBase, Provide) {
InSequence s;
DictionaryValue* policies = new DictionaryValue();
@@ -25,10 +26,12 @@ TEST_F(AsynchronousPolicyTestBase, Provide) {
EXPECT_CALL(*store_, Apply(policy::kPolicySyncDisabled, _)).Times(1);
AsynchronousPolicyProvider provider(
ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
- new AsynchronousPolicyLoader(delegate_.release()));
+ new AsynchronousPolicyLoader(delegate_.release(), 10));
provider.Provide(store_.get());
}
+
+// Trigger a refresh manually and ensure that policy gets reloaded.
TEST_F(AsynchronousPolicyTestBase, ProvideAfterRefresh) {
InSequence s;
DictionaryValue* original_policies = new DictionaryValue();
@@ -39,8 +42,8 @@ TEST_F(AsynchronousPolicyTestBase, ProvideAfterRefresh) {
policy::key::kJavascriptEnabled,
true);
EXPECT_CALL(*delegate_, Load()).WillOnce(Return(refresh_policies));
- AsynchronousPolicyLoader* loader = new AsynchronousPolicyLoader(
- delegate_.release());
+ AsynchronousPolicyLoader* loader =
+ new AsynchronousPolicyLoader(delegate_.release(), 10);
AsynchronousPolicyProvider provider(
ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList(),
loader);
diff --git a/chrome/browser/policy/configuration_policy_loader_win.cc b/chrome/browser/policy/configuration_policy_loader_win.cc
new file mode 100644
index 0000000..68ccf80
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_loader_win.cc
@@ -0,0 +1,90 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/configuration_policy_loader_win.h"
+
+#include <userenv.h>
+
+#include "chrome/browser/browser_thread.h"
+
+namespace policy {
+
+ConfigurationPolicyLoaderWin::ConfigurationPolicyLoaderWin(
+ AsynchronousPolicyProvider::Delegate* delegate,
+ int reload_interval_minutes)
+ : AsynchronousPolicyLoader(delegate, reload_interval_minutes),
+ user_policy_changed_event_(false, false),
+ machine_policy_changed_event_(false, false),
+ user_policy_watcher_failed_(false),
+ machine_policy_watcher_failed_(false) {
+ if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
+ PLOG(WARNING) << "Failed to register user group policy notification";
+ user_policy_watcher_failed_ = true;
+ }
+ if (!RegisterGPNotification(machine_policy_changed_event_.handle(), true)) {
+ PLOG(WARNING) << "Failed to register machine group policy notification.";
+ machine_policy_watcher_failed_ = true;
+ }
+}
+
+void ConfigurationPolicyLoaderWin::InitOnFileThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ AsynchronousPolicyLoader::InitOnFileThread();
+ MessageLoop::current()->AddDestructionObserver(this);
+ SetupWatches();
+}
+
+void ConfigurationPolicyLoaderWin::StopOnFileThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ MessageLoop::current()->RemoveDestructionObserver(this);
+ user_policy_watcher_.StopWatching();
+ machine_policy_watcher_.StopWatching();
+ AsynchronousPolicyLoader::StopOnFileThread();
+}
+
+void ConfigurationPolicyLoaderWin::SetupWatches() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ CancelReloadTask();
+
+ if (!user_policy_watcher_failed_ &&
+ !user_policy_watcher_.GetWatchedObject() &&
+ !user_policy_watcher_.StartWatching(
+ user_policy_changed_event_.handle(), this)) {
+ LOG(WARNING) << "Failed to start watch for user policy change event";
+ user_policy_watcher_failed_ = true;
+ }
+ if (!machine_policy_watcher_failed_ &&
+ !machine_policy_watcher_.GetWatchedObject() &&
+ !machine_policy_watcher_.StartWatching(
+ machine_policy_changed_event_.handle(), this)) {
+ LOG(WARNING) << "Failed to start watch for machine policy change event";
+ machine_policy_watcher_failed_ = true;
+ }
+
+ if (user_policy_watcher_failed_ || machine_policy_watcher_failed_)
+ ScheduleFallbackReloadTask();
+}
+
+void ConfigurationPolicyLoaderWin::Reload() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ AsynchronousPolicyLoader::Reload();
+ SetupWatches();
+}
+
+void ConfigurationPolicyLoaderWin::OnObjectSignaled(HANDLE object) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+ DCHECK(object == user_policy_changed_event_.handle() ||
+ object == machine_policy_changed_event_.handle())
+ << "unexpected object signaled policy reload, obj = "
+ << std::showbase << std::hex << object;
+ Reload();
+}
+
+void ConfigurationPolicyLoaderWin::
+ WillDestroyCurrentMessageLoop() {
+ CancelReloadTask();
+ MessageLoop::current()->RemoveDestructionObserver(this);
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_loader_win.h b/chrome/browser/policy/configuration_policy_loader_win.h
new file mode 100644
index 0000000..a898afc
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_loader_win.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_LOADER_WIN_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_LOADER_WIN_H_
+#pragma once
+
+#include "base/object_watcher.h"
+#include "base/waitable_event.h"
+#include "chrome/browser/policy/asynchronous_policy_loader.h"
+
+namespace policy {
+
+// Keeps watch on Windows Group Policy notification event to trigger a policy
+// reload when Group Policy changes.
+class ConfigurationPolicyLoaderWin
+ : public AsynchronousPolicyLoader,
+ public base::ObjectWatcher::Delegate,
+ public MessageLoop::DestructionObserver {
+ public:
+ ConfigurationPolicyLoaderWin(
+ AsynchronousPolicyProvider::Delegate* delegate,
+ int reload_interval_minutes);
+ virtual ~ConfigurationPolicyLoaderWin() {}
+
+ protected:
+ // AsynchronousPolicyLoader overrides:
+ virtual void InitOnFileThread();
+ virtual void StopOnFileThread();
+
+ private:
+ // Updates the watchers and schedules the reload task if appropriate.
+ void SetupWatches();
+
+ // Post a reload notification and update the watch machinery.
+ void Reload();
+
+ // ObjectWatcher::Delegate overrides:
+ virtual void OnObjectSignaled(HANDLE object);
+
+ // MessageLoop::DestructionObserver overrides:
+ virtual void WillDestroyCurrentMessageLoop();
+
+ base::WaitableEvent user_policy_changed_event_;
+ base::WaitableEvent machine_policy_changed_event_;
+ base::ObjectWatcher user_policy_watcher_;
+ base::ObjectWatcher machine_policy_watcher_;
+ bool user_policy_watcher_failed_;
+ bool machine_policy_watcher_failed_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyLoaderWin);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_LOADER_WIN_H_
diff --git a/chrome/browser/policy/configuration_policy_provider_delegate_win.cc b/chrome/browser/policy/configuration_policy_provider_delegate_win.cc
new file mode 100644
index 0000000..68947de
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_delegate_win.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/policy/configuration_policy_provider_delegate_win.h"
+
+#include "base/string_number_conversions.h"
+#include "base/utf_string_conversions.h"
+#include "base/win/registry.h"
+#include "chrome/common/policy_constants.h"
+
+using base::win::RegKey;
+
+namespace {
+
+bool ReadRegistryStringValue(RegKey* key, const string16& name,
+ string16* result) {
+ DWORD value_size = 0;
+ DWORD key_type = 0;
+ scoped_array<uint8> buffer;
+
+ if (!key->ReadValue(name.c_str(), 0, &value_size, &key_type))
+ return false;
+ if (key_type != REG_SZ)
+ return false;
+
+ // According to the Microsoft documentation, the string
+ // buffer may not be explicitly 0-terminated. Allocate a
+ // slightly larger buffer and pre-fill to zeros to guarantee
+ // the 0-termination.
+ buffer.reset(new uint8[value_size + 2]);
+ memset(buffer.get(), 0, value_size + 2);
+ key->ReadValue(name.c_str(), buffer.get(), &value_size, NULL);
+ result->assign(reinterpret_cast<const wchar_t*>(buffer.get()));
+ return true;
+}
+
+} // namespace
+
+namespace policy {
+
+ConfigurationPolicyProviderDelegateWin::ConfigurationPolicyProviderDelegateWin(
+ const ConfigurationPolicyProvider::PolicyDefinitionList*
+ policy_definition_list)
+ : policy_definition_list_(policy_definition_list) {
+}
+
+DictionaryValue* ConfigurationPolicyProviderDelegateWin::Load() {
+ DictionaryValue* result = new DictionaryValue();
+ const ConfigurationPolicyProvider::PolicyDefinitionList::Entry* current;
+ for (current = policy_definition_list_->begin;
+ current != policy_definition_list_->end;
+ ++current) {
+ const string16 name(ASCIIToUTF16(current->name));
+ switch (current->value_type) {
+ case Value::TYPE_STRING: {
+ string16 string_value;
+ if (GetRegistryPolicyString(name, &string_value)) {
+ result->SetString(current->name, string_value);
+ }
+ break;
+ }
+ case Value::TYPE_LIST: {
+ scoped_ptr<ListValue> list_value(new ListValue);
+ if (GetRegistryPolicyStringList(name, list_value.get()))
+ result->Set(current->name, list_value.release());
+ break;
+ }
+ case Value::TYPE_BOOLEAN: {
+ bool bool_value;
+ if (GetRegistryPolicyBoolean(name, &bool_value)) {
+ result->SetBoolean(current->name, bool_value);
+ }
+ break;
+ }
+ case Value::TYPE_INTEGER: {
+ uint32 int_value;
+ if (GetRegistryPolicyInteger(name, &int_value)) {
+ result->SetInteger(current->name, int_value);
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ }
+ return result;
+}
+
+bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyString(
+ const string16& name, string16* result) const {
+ string16 path = string16(kRegistrySubKey);
+ RegKey policy_key;
+ // First try the global policy.
+ if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
+ if (ReadRegistryStringValue(&policy_key, name, result))
+ return true;
+ policy_key.Close();
+ }
+ // Fall back on user-specific policy.
+ if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
+ return false;
+ return ReadRegistryStringValue(&policy_key, name, result);
+}
+
+bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyStringList(
+ const string16& key, ListValue* result) const {
+ string16 path = string16(kRegistrySubKey);
+ path += ASCIIToUTF16("\\") + key;
+ RegKey policy_key;
+ if (!policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
+ policy_key.Close();
+ // Fall back on user-specific policy.
+ if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
+ return false;
+ }
+ string16 policy_string;
+ int index = 0;
+ while (ReadRegistryStringValue(&policy_key, base::IntToString16(++index),
+ &policy_string)) {
+ result->Append(Value::CreateStringValue(policy_string));
+ }
+ return true;
+}
+
+bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyBoolean(
+ const string16& value_name, bool* result) const {
+ DWORD value;
+ RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
+ if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
+ *result = value != 0;
+ return true;
+ }
+
+ RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
+ if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
+ *result = value != 0;
+ return true;
+ }
+ return false;
+}
+
+bool ConfigurationPolicyProviderDelegateWin::GetRegistryPolicyInteger(
+ const string16& value_name, uint32* result) const {
+ DWORD value;
+ RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
+ if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
+ *result = value;
+ return true;
+ }
+
+ RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
+ if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
+ *result = value;
+ return true;
+ }
+ return false;
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_provider_delegate_win.h b/chrome/browser/policy/configuration_policy_provider_delegate_win.h
new file mode 100644
index 0000000..63d36b2
--- /dev/null
+++ b/chrome/browser/policy/configuration_policy_provider_delegate_win.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_DELEGATE_WIN_H_
+#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_DELEGATE_WIN_H_
+#pragma once
+
+#include "chrome/browser/policy/asynchronous_policy_provider.h"
+
+namespace policy {
+
+class ConfigurationPolicyProviderDelegateWin
+ : public AsynchronousPolicyProvider::Delegate {
+ public:
+ ConfigurationPolicyProviderDelegateWin(
+ const ConfigurationPolicyProvider::PolicyDefinitionList*
+ policy_definition_list);
+ virtual ~ConfigurationPolicyProviderDelegateWin() {}
+
+ // AsynchronousPolicyProvider::Delegate overrides:
+ virtual DictionaryValue* Load();
+
+ private:
+ // Methods to perform type-specific policy lookups in the registry.
+ // HKLM is checked first, then HKCU.
+
+ // Reads a string registry value |name| at the specified |key| and puts the
+ // resulting string in |result|.
+ bool GetRegistryPolicyString(const string16& name, string16* result) const;
+ // Gets a list value contained under |key| one level below the policy root.
+ bool GetRegistryPolicyStringList(const string16& key,
+ ListValue* result) const;
+ bool GetRegistryPolicyBoolean(const string16& value_name,
+ bool* result) const;
+ bool GetRegistryPolicyInteger(const string16& value_name,
+ uint32* result) const;
+
+ const ConfigurationPolicyProvider::PolicyDefinitionList*
+ policy_definition_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderDelegateWin);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_DELEGATE_WIN_H_
diff --git a/chrome/browser/policy/configuration_policy_provider_win.cc b/chrome/browser/policy/configuration_policy_provider_win.cc
index 084f130..df336d3 100644
--- a/chrome/browser/policy/configuration_policy_provider_win.cc
+++ b/chrome/browser/policy/configuration_policy_provider_win.cc
@@ -4,290 +4,22 @@
#include "chrome/browser/policy/configuration_policy_provider_win.h"
-#include <userenv.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/object_watcher.h"
-#include "base/scoped_ptr.h"
-#include "base/string_number_conversions.h"
-#include "base/string_piece.h"
-#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
-#include "base/thread_restrictions.h"
-#include "base/utf_string_conversions.h"
-#include "base/values.h"
-#include "base/win/registry.h"
-#include "chrome/common/policy_constants.h"
-
-using base::win::RegKey;
+#include "chrome/browser/policy/asynchronous_policy_provider.h"
+#include "chrome/browser/policy/configuration_policy_loader_win.h"
+#include "chrome/browser/policy/configuration_policy_provider_delegate_win.h"
namespace policy {
-namespace {
-
-bool ReadRegistryStringValue(RegKey* key, const string16& name,
- string16* result) {
- DWORD value_size = 0;
- DWORD key_type = 0;
- scoped_array<uint8> buffer;
-
- if (!key->ReadValue(name.c_str(), 0, &value_size, &key_type))
- return false;
- if (key_type != REG_SZ)
- return false;
-
- // According to the Microsoft documentation, the string
- // buffer may not be explicitly 0-terminated. Allocate a
- // slightly larger buffer and pre-fill to zeros to guarantee
- // the 0-termination.
- buffer.reset(new uint8[value_size + 2]);
- memset(buffer.get(), 0, value_size + 2);
- key->ReadValue(name.c_str(), buffer.get(), &value_size, NULL);
- result->assign(reinterpret_cast<const wchar_t*>(buffer.get()));
- return true;
-}
-
-} // namespace
-
// Period at which to run the reload task in case the group policy change
// watchers fail.
const int kReloadIntervalMinutes = 15;
-ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
- GroupPolicyChangeWatcher(
- base::WeakPtr<ConfigurationPolicyProviderWin> provider,
- int reload_interval_minutes)
- : provider_(provider),
- user_policy_changed_event_(false, false),
- machine_policy_changed_event_(false, false),
- user_policy_watcher_failed_(false),
- machine_policy_watcher_failed_(false),
- reload_interval_minutes_(reload_interval_minutes),
- reload_task_(NULL) {
- if (!RegisterGPNotification(user_policy_changed_event_.handle(), false)) {
- PLOG(WARNING) << "Failed to register user group policy notification";
- user_policy_watcher_failed_ = true;
- }
- if (!RegisterGPNotification(machine_policy_changed_event_.handle(), true)) {
- PLOG(WARNING) << "Failed to register machine group policy notification.";
- machine_policy_watcher_failed_ = true;
- }
-}
-
-ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
- ~GroupPolicyChangeWatcher() {
- if (MessageLoop::current())
- MessageLoop::current()->RemoveDestructionObserver(this);
- DCHECK(!reload_task_);
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::Start() {
- MessageLoop::current()->AddDestructionObserver(this);
- SetupWatches();
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::Stop() {
- user_policy_watcher_.StopWatching();
- machine_policy_watcher_.StopWatching();
- if (reload_task_) {
- reload_task_->Cancel();
- reload_task_ = NULL;
- }
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::SetupWatches() {
- if (reload_task_) {
- reload_task_->Cancel();
- reload_task_ = NULL;
- }
-
- if (!user_policy_watcher_failed_) {
- if (!user_policy_watcher_.GetWatchedObject() &&
- !user_policy_watcher_.StartWatching(
- user_policy_changed_event_.handle(), this)) {
- LOG(WARNING) << "Failed to start watch for user policy change event";
- user_policy_watcher_failed_ = true;
- }
- }
- if (!machine_policy_watcher_failed_) {
- if (!machine_policy_watcher_.GetWatchedObject() &&
- !machine_policy_watcher_.StartWatching(
- machine_policy_changed_event_.handle(), this)) {
- LOG(WARNING) << "Failed to start watch for machine policy change event";
- machine_policy_watcher_failed_ = true;
- }
- }
-
- if (user_policy_watcher_failed_ || machine_policy_watcher_failed_) {
- reload_task_ =
- NewRunnableMethod(this, &GroupPolicyChangeWatcher::ReloadFromTask);
- int64 delay =
- base::TimeDelta::FromMinutes(reload_interval_minutes_).InMilliseconds();
- MessageLoop::current()->PostDelayedTask(FROM_HERE, reload_task_, delay);
- }
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::Reload() {
- if (provider_.get())
- provider_->NotifyStoreOfPolicyChange();
- SetupWatches();
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
- ReloadFromTask() {
- // Make sure to not call Cancel() on the task, since it might hold the last
- // reference that keeps this object alive.
- reload_task_ = NULL;
- Reload();
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
- OnObjectSignaled(HANDLE object) {
- DCHECK(object == user_policy_changed_event_.handle() ||
- object == machine_policy_changed_event_.handle())
- << "unexpected object signaled policy reload, obj = "
- << std::showbase << std::hex << object;
- Reload();
-}
-
-void ConfigurationPolicyProviderWin::GroupPolicyChangeWatcher::
- WillDestroyCurrentMessageLoop() {
- reload_task_ = NULL;
- MessageLoop::current()->RemoveDestructionObserver(this);
-}
-
ConfigurationPolicyProviderWin::ConfigurationPolicyProviderWin(
const PolicyDefinitionList* policy_list)
- : ConfigurationPolicyProvider(policy_list) {
- watcher_ = new GroupPolicyChangeWatcher(this->AsWeakPtr(),
- kReloadIntervalMinutes);
- watcher_->Start();
-}
-
-ConfigurationPolicyProviderWin::~ConfigurationPolicyProviderWin() {
- watcher_->Stop();
-}
-
-bool ConfigurationPolicyProviderWin::GetRegistryPolicyString(
- const string16& name, string16* result) const {
- string16 path = string16(kRegistrySubKey);
- RegKey policy_key;
- // First try the global policy.
- if (policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
- if (ReadRegistryStringValue(&policy_key, name, result))
- return true;
- policy_key.Close();
- }
- // Fall back on user-specific policy.
- if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
- return false;
- return ReadRegistryStringValue(&policy_key, name, result);
-}
-
-bool ConfigurationPolicyProviderWin::GetRegistryPolicyStringList(
- const string16& key, ListValue* result) const {
- string16 path = string16(kRegistrySubKey);
- path += ASCIIToUTF16("\\") + key;
- RegKey policy_key;
- if (!policy_key.Open(HKEY_LOCAL_MACHINE, path.c_str(), KEY_READ)) {
- policy_key.Close();
- // Fall back on user-specific policy.
- if (!policy_key.Open(HKEY_CURRENT_USER, path.c_str(), KEY_READ))
- return false;
- }
- string16 policy_string;
- int index = 0;
- while (ReadRegistryStringValue(&policy_key, base::IntToString16(++index),
- &policy_string)) {
- result->Append(Value::CreateStringValue(policy_string));
- }
- return true;
-}
-
-bool ConfigurationPolicyProviderWin::GetRegistryPolicyBoolean(
- const string16& value_name, bool* result) const {
- DWORD value;
- RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
- if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
- *result = value != 0;
- return true;
- }
-
- RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
- if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
- *result = value != 0;
- return true;
- }
- return false;
-}
-
-bool ConfigurationPolicyProviderWin::GetRegistryPolicyInteger(
- const string16& value_name, uint32* result) const {
- DWORD value;
- RegKey hkcu_policy_key(HKEY_LOCAL_MACHINE, kRegistrySubKey, KEY_READ);
- if (hkcu_policy_key.ReadValueDW(value_name.c_str(), &value)) {
- *result = value;
- return true;
- }
-
- RegKey hklm_policy_key(HKEY_CURRENT_USER, kRegistrySubKey, KEY_READ);
- if (hklm_policy_key.ReadValueDW(value_name.c_str(), &value)) {
- *result = value;
- return true;
- }
- return false;
-}
-
-bool ConfigurationPolicyProviderWin::Provide(
- ConfigurationPolicyStoreInterface* store) {
- // This function calls GetRegistryPolicy* which hit up the registry. Those
- // are I/O functions not allowed to be called on the main thread.
- // http://crbug.com/66453
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- const PolicyDefinitionList* policy_list(policy_definition_list());
- for (const PolicyDefinitionList::Entry* current = policy_list->begin;
- current != policy_list->end; ++current) {
- std::wstring name = UTF8ToWide(current->name);
- switch (current->value_type) {
- case Value::TYPE_STRING: {
- std::wstring string_value;
- if (GetRegistryPolicyString(name.c_str(), &string_value)) {
- store->Apply(current->policy_type,
- Value::CreateStringValue(string_value));
- }
- break;
- }
- case Value::TYPE_LIST: {
- scoped_ptr<ListValue> list_value(new ListValue);
- if (GetRegistryPolicyStringList(name.c_str(), list_value.get()))
- store->Apply(current->policy_type, list_value.release());
- break;
- }
- case Value::TYPE_BOOLEAN: {
- bool bool_value;
- if (GetRegistryPolicyBoolean(name.c_str(), &bool_value)) {
- store->Apply(current->policy_type,
- Value::CreateBooleanValue(bool_value));
- }
- break;
- }
- case Value::TYPE_INTEGER: {
- uint32 int_value;
- if (GetRegistryPolicyInteger(name.c_str(), &int_value)) {
- store->Apply(current->policy_type,
- Value::CreateIntegerValue(int_value));
- }
- break;
- }
- default:
- NOTREACHED();
- return false;
- }
- }
-
- return true;
-}
+ : AsynchronousPolicyProvider(
+ policy_list,
+ new ConfigurationPolicyLoaderWin(
+ new ConfigurationPolicyProviderDelegateWin(policy_list),
+ kReloadIntervalMinutes)) {}
} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_provider_win.h b/chrome/browser/policy/configuration_policy_provider_win.h
index c2d5509..31e4a2b 100644
--- a/chrome/browser/policy/configuration_policy_provider_win.h
+++ b/chrome/browser/policy/configuration_policy_provider_win.h
@@ -6,19 +6,7 @@
#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_PROVIDER_WIN_H_
#pragma once
-#include "base/object_watcher.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "base/waitable_event.h"
-#include "base/weak_ptr.h"
-#include "chrome/browser/policy/configuration_policy_store_interface.h"
-#include "chrome/browser/policy/configuration_policy_provider.h"
-
-namespace base {
-namespace win {
-class RegKey;
-} // namespace win
-} // namespace base
+#include "chrome/browser/policy/asynchronous_policy_provider.h"
namespace policy {
@@ -28,89 +16,14 @@ namespace policy {
// On a managed machine in a domain, this portion of the registry is
// periodically updated by the Windows Group Policy machinery to contain
// the latest version of the policy set by administrators.
-class ConfigurationPolicyProviderWin
- : public ConfigurationPolicyProvider,
- public base::SupportsWeakPtr<ConfigurationPolicyProviderWin> {
+class ConfigurationPolicyProviderWin : public AsynchronousPolicyProvider {
public:
- // Keeps watch on Windows Group Policy notification event to trigger a policy
- // reload when Group Policy changes. This class is reference counted to
- // facilitate timer-based reloads through the message loop. It is not safe to
- // access GroupPolicyChangeWatcher concurrently from multiple threads.
- class GroupPolicyChangeWatcher
- : public base::ObjectWatcher::Delegate,
- public MessageLoop::DestructionObserver,
- public base::RefCountedThreadSafe<GroupPolicyChangeWatcher> {
- public:
- GroupPolicyChangeWatcher(
- base::WeakPtr<ConfigurationPolicyProviderWin> provider,
- int reload_interval_minutes);
- virtual ~GroupPolicyChangeWatcher();
-
- // Start watching.
- void Start();
-
- // Stop any pending watch activity in order to allow for timely shutdown.
- void Stop();
-
- private:
- // Updates the watchers and schedules the reload task if appropriate.
- void SetupWatches();
-
- // Post a reload notification and update the watch machinery.
- void Reload();
-
- // Called for timer-based refresh from the message loop.
- void ReloadFromTask();
-
- // ObjectWatcher::Delegate implementation:
- virtual void OnObjectSignaled(HANDLE object);
-
- // MessageLoop::DestructionObserver implementation:
- virtual void WillDestroyCurrentMessageLoop();
-
- base::WeakPtr<ConfigurationPolicyProviderWin> provider_;
- base::WaitableEvent user_policy_changed_event_;
- base::WaitableEvent machine_policy_changed_event_;
- base::ObjectWatcher user_policy_watcher_;
- base::ObjectWatcher machine_policy_watcher_;
- bool user_policy_watcher_failed_;
- bool machine_policy_watcher_failed_;
-
- // Period to schedule the reload task at.
- int reload_interval_minutes_;
-
- // A reference to a delayed task for timer-based reloading.
- CancelableTask* reload_task_;
- };
-
explicit ConfigurationPolicyProviderWin(
const PolicyDefinitionList* policy_list);
- virtual ~ConfigurationPolicyProviderWin();
-
- // ConfigurationPolicyProvider method overrides:
- virtual bool Provide(ConfigurationPolicyStoreInterface* store);
-
- protected:
- // The sub key path for Chromium's Group Policy information in the
- // Windows registry.
- static const wchar_t kPolicyRegistrySubKey[];
+ virtual ~ConfigurationPolicyProviderWin() {}
private:
- scoped_refptr<GroupPolicyChangeWatcher> watcher_;
-
- // Methods to perform type-specific policy lookups in the registry.
- // HKLM is checked first, then HKCU.
-
- // Reads a string registry value |name| at the specified |key| and puts the
- // resulting string in |result|.
- bool GetRegistryPolicyString(const string16& name, string16* result) const;
- // Gets a list value contained under |key| one level below the policy root.
- bool GetRegistryPolicyStringList(const string16& key,
- ListValue* result) const;
- bool GetRegistryPolicyBoolean(const string16& value_name,
- bool* result) const;
- bool GetRegistryPolicyInteger(const string16& value_name,
- uint32* result) const;
+ DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderWin);
};
} // namespace policy
diff --git a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
index 39c4dce..78c6f7b 100644
--- a/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_provider_win_unittest.cc
@@ -3,15 +3,17 @@
// found in the LICENSE file.
#include <gtest/gtest.h>
-
#include <windows.h>
+#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "base/stl_util-inl.h"
#include "base/string_number_conversions.h"
#include "base/string_piece.h"
#include "base/utf_string_conversions.h"
#include "base/win/registry.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/policy/asynchronous_policy_loader.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/configuration_policy_provider_win.h"
#include "chrome/browser/policy/mock_configuration_policy_store.h"
@@ -151,13 +153,16 @@ class ConfigurationPolicyProviderWinTest
scoped_ptr<MockConfigurationPolicyStore> store_;
scoped_ptr<ConfigurationPolicyProviderWin> provider_;
- private:
// A message loop must be declared and instantiated for these tests,
// because Windows policy provider create WaitableEvents and
// ObjectWatchers that require the tests to have a MessageLoop associated
// with the thread executing the tests.
MessageLoop loop_;
+ private:
+ BrowserThread ui_thread_;
+ BrowserThread file_thread_;
+
// Keys are created for the lifetime of a test to contain
// the sandboxed HKCU and HKLM hives, respectively.
RegKey temp_hkcu_hive_key_;
@@ -165,7 +170,9 @@ class ConfigurationPolicyProviderWinTest
};
ConfigurationPolicyProviderWinTest::ConfigurationPolicyProviderWinTest()
- : temp_hklm_hive_key_(HKEY_CURRENT_USER, kUnitTestMachineOverrideSubKey,
+ : ui_thread_(BrowserThread::UI, &loop_),
+ file_thread_(BrowserThread::FILE, &loop_),
+ temp_hklm_hive_key_(HKEY_CURRENT_USER, kUnitTestMachineOverrideSubKey,
KEY_READ),
temp_hkcu_hive_key_(HKEY_CURRENT_USER, kUnitTestUserOverrideSubKey,
KEY_READ) {
@@ -194,6 +201,7 @@ void ConfigurationPolicyProviderWinTest::SetUp() {
void ConfigurationPolicyProviderWinTest::TearDown() {
DeactivateOverrides();
DeleteRegistrySandbox();
+ loop_.RunAllPending();
}
void ConfigurationPolicyProviderWinTest::ActivateOverrides() {
@@ -299,6 +307,8 @@ TEST_P(ConfigurationPolicyProviderWinTest, InvalidValue) {
WriteInvalidValue(HKEY_CURRENT_USER,
GetParam().policy_name(),
GetParam().hkcu_value());
+ provider_->loader()->Reload();
+ loop_.RunAllPending();
provider_->Provide(store_.get());
EXPECT_TRUE(store_->policy_map().empty());
}
@@ -307,6 +317,8 @@ TEST_P(ConfigurationPolicyProviderWinTest, HKLM) {
WriteValue(HKEY_LOCAL_MACHINE,
GetParam().policy_name(),
GetParam().hklm_value());
+ provider_->loader()->Reload();
+ loop_.RunAllPending();
provider_->Provide(store_.get());
const Value* value = store_->Get(GetParam().type());
ASSERT_TRUE(value);
@@ -317,6 +329,8 @@ TEST_P(ConfigurationPolicyProviderWinTest, HKCU) {
WriteValue(HKEY_CURRENT_USER,
GetParam().policy_name(),
GetParam().hkcu_value());
+ provider_->loader()->Reload();
+ loop_.RunAllPending();
provider_->Provide(store_.get());
const Value* value = store_->Get(GetParam().type());
ASSERT_TRUE(value);
@@ -330,6 +344,8 @@ TEST_P(ConfigurationPolicyProviderWinTest, HKLMOverHKCU) {
WriteValue(HKEY_CURRENT_USER,
GetParam().policy_name(),
GetParam().hkcu_value());
+ provider_->loader()->Reload();
+ loop_.RunAllPending();
provider_->Provide(store_.get());
const Value* value = store_->Get(GetParam().type());
ASSERT_TRUE(value);
diff --git a/chrome/browser/policy/file_based_policy_loader.cc b/chrome/browser/policy/file_based_policy_loader.cc
index 5d49f98..4da6192 100644
--- a/chrome/browser/policy/file_based_policy_loader.cc
+++ b/chrome/browser/policy/file_based_policy_loader.cc
@@ -21,13 +21,14 @@ namespace policy {
FileBasedPolicyLoader::FileBasedPolicyLoader(
FileBasedPolicyProvider::ProviderDelegate* provider_delegate)
- : AsynchronousPolicyLoader(provider_delegate),
+ : AsynchronousPolicyLoader(provider_delegate,
+ kReloadIntervalMinutes),
config_file_path_(provider_delegate->config_file_path()),
- reload_task_(NULL),
- reload_interval_(base::TimeDelta::FromMinutes(kReloadIntervalMinutes)),
settle_interval_(base::TimeDelta::FromSeconds(kSettleIntervalSeconds)) {
}
+FileBasedPolicyLoader::~FileBasedPolicyLoader() {}
+
class FileBasedPolicyWatcherDelegate : public FilePathWatcher::Delegate {
public:
explicit FileBasedPolicyWatcherDelegate(
@@ -49,27 +50,6 @@ class FileBasedPolicyWatcherDelegate : public FilePathWatcher::Delegate {
DISALLOW_COPY_AND_ASSIGN(FileBasedPolicyWatcherDelegate);
};
-void FileBasedPolicyLoader::Init() {
- AsynchronousPolicyLoader::Init();
-
- // Initialization can happen early when the file thread is not yet available,
- // but the watcher's initialization must be done on the file thread. Posting
- // to a to the file directly before the file thread is initialized will cause
- // the task to be forgotten. Instead, post a task to the ui thread to delay
- // the remainder of initialization until threading is fully initialized.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(this,
- &FileBasedPolicyLoader::InitAfterFileThreadAvailable));
-}
-
-void FileBasedPolicyLoader::Stop() {
- AsynchronousPolicyLoader::Stop();
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &FileBasedPolicyLoader::StopOnFileThread));
-}
-
void FileBasedPolicyLoader::OnFilePathChanged(
const FilePath& path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
@@ -81,8 +61,6 @@ void FileBasedPolicyLoader::OnError() {
<< " failed.";
}
-FileBasedPolicyLoader::~FileBasedPolicyLoader() {}
-
void FileBasedPolicyLoader::Reload() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
@@ -111,14 +89,6 @@ void FileBasedPolicyLoader::Reload() {
ScheduleFallbackReloadTask();
}
-void FileBasedPolicyLoader::InitAfterFileThreadAvailable() {
- if (provider()) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &FileBasedPolicyLoader::InitOnFileThread));
- }
-}
-
void FileBasedPolicyLoader::InitOnFileThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
watcher_.reset(new FilePathWatcher);
@@ -138,40 +108,7 @@ void FileBasedPolicyLoader::InitOnFileThread() {
void FileBasedPolicyLoader::StopOnFileThread() {
watcher_.reset();
- if (reload_task_) {
- reload_task_->Cancel();
- reload_task_ = NULL;
- }
-}
-
-void FileBasedPolicyLoader::ScheduleReloadTask(
- const base::TimeDelta& delay) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- if (reload_task_)
- reload_task_->Cancel();
-
- reload_task_ =
- NewRunnableMethod(this, &FileBasedPolicyLoader::ReloadFromTask);
- BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, reload_task_,
- delay.InMilliseconds());
-}
-
-void FileBasedPolicyLoader::ScheduleFallbackReloadTask() {
- // As a safeguard in case that the load delegate failed to timely notice a
- // change in policy, schedule a reload task that'll make us recheck after a
- // reasonable interval.
- ScheduleReloadTask(reload_interval_);
-}
-
-void FileBasedPolicyLoader::ReloadFromTask() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-
- // Drop the reference to the reload task, since the task might be the only
- // referer that keeps us alive, so we should not Cancel() it.
- reload_task_ = NULL;
-
- Reload();
+ AsynchronousPolicyLoader::StopOnFileThread();
}
bool FileBasedPolicyLoader::IsSafeToReloadPolicy(
diff --git a/chrome/browser/policy/file_based_policy_loader.h b/chrome/browser/policy/file_based_policy_loader.h
index f718e8d..97c3198 100644
--- a/chrome/browser/policy/file_based_policy_loader.h
+++ b/chrome/browser/policy/file_based_policy_loader.h
@@ -21,9 +21,7 @@ class FileBasedPolicyLoader : public AsynchronousPolicyLoader {
FileBasedPolicyLoader(
FileBasedPolicyProvider::ProviderDelegate* provider_delegate);
- // AsynchronousPolicyLoader implementation:
- virtual void Init();
- virtual void Stop();
+ // AsynchronousPolicyLoader overrides:
virtual void Reload();
void OnFilePathChanged(const FilePath& path);
@@ -37,30 +35,14 @@ class FileBasedPolicyLoader : public AsynchronousPolicyLoader {
const FilePath& config_file_path() { return config_file_path_; }
- private:
- // Finishes initialization after the threading system has been fully
- // intiialized.
- void InitAfterFileThreadAvailable();
-
- // Creates the file path watcher, configures it to watch |config_file_path_|
- // and schedules the fallback reload task. Must be called on the file thread.
- void InitOnFileThread();
-
- // Cancels file path watch notification and destroys the watcher.
- // Must be called on file thread.
- void StopOnFileThread();
-
- // Schedules a reload task to run when |delay| expires. Must be called on the
- // file thread.
- void ScheduleReloadTask(const base::TimeDelta& delay);
+ // AsynchronousPolicyLoader overrides:
- // Schedules a reload task to run after the number of minutes specified
- // in |reload_interval_minutes_|. Must be called on the file thread.
- void ScheduleFallbackReloadTask();
-
- // Invoked from the reload task on the file thread.
- void ReloadFromTask();
+ // Creates the file path watcher and configures it to watch
+ // |config_file_path_|. Must be called on the file thread.
+ virtual void InitOnFileThread();
+ virtual void StopOnFileThread();
+ private:
// Checks whether policy information is safe to read. If not, returns false
// and then delays until it is considered safe to reload in |delay|.
// Must be called on the file thread.
@@ -76,14 +58,6 @@ class FileBasedPolicyLoader : public AsynchronousPolicyLoader {
// loader and keeps it alive.
scoped_ptr<FilePathWatcher> watcher_;
- // The reload task. Access only on the file thread. Holds a reference to the
- // currently posted task, so we can cancel and repost it if necessary.
- CancelableTask* reload_task_;
-
- // The interval that a policy reload will be triggered as a fallback even if
- // the delegate doesn't indicate that one is needed.
- const base::TimeDelta reload_interval_;
-
// Settle interval.
const base::TimeDelta settle_interval_;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index d403c46..153568d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1977,12 +1977,16 @@
'browser/policy/asynchronous_policy_provider.h',
'browser/policy/config_dir_policy_provider.cc',
'browser/policy/config_dir_policy_provider.h',
+ 'browser/policy/configuration_policy_loader_win.cc',
+ 'browser/policy/configuration_policy_loader_win.h',
'browser/policy/configuration_policy_pref_store.cc',
'browser/policy/configuration_policy_pref_store.h',
'browser/policy/configuration_policy_provider.cc',
'browser/policy/configuration_policy_provider.cc',
'browser/policy/configuration_policy_provider.h',
'browser/policy/configuration_policy_provider.h',
+ 'browser/policy/configuration_policy_provider_delegate_win.cc',
+ 'browser/policy/configuration_policy_provider_delegate_win.h',
'browser/policy/configuration_policy_provider_mac.cc',
'browser/policy/configuration_policy_provider_mac.h',
'browser/policy/configuration_policy_provider_win.cc',