Index: chrome/browser/policy/config_dir_policy_provider.cc |
=================================================================== |
--- chrome/browser/policy/config_dir_policy_provider.cc (revision 56841) |
+++ chrome/browser/policy/config_dir_policy_provider.cc (working copy) |
@@ -8,109 +8,22 @@ |
#include "base/file_util.h" |
#include "base/logging.h" |
+#include "base/scoped_ptr.h" |
#include "base/utf_string_conversions.h" |
#include "base/values.h" |
#include "chrome/common/json_value_serializer.h" |
-namespace { |
- |
-// Amount of time we wait for the files in the policy directory to settle before |
-// trying to load it. This alleviates the problem of reading partially written |
-// files and allows to batch quasi-simultaneous changes. |
-const int kSettleIntervalSeconds = 5; |
- |
-// The time interval for rechecking policy. This is our fallback in case the |
-// directory watch fails or doesn't report a change. |
-const int kReloadIntervalMinutes = 15; |
- |
-} // namespace |
- |
-// PolicyDirLoader implementation: |
- |
-PolicyDirLoader::PolicyDirLoader( |
- base::WeakPtr<ConfigDirPolicyProvider> provider, |
- const FilePath& config_dir, |
- int settle_interval_seconds, |
- int reload_interval_minutes) |
- : provider_(provider), |
- origin_loop_(MessageLoop::current()), |
- config_dir_(config_dir), |
- reload_task_(NULL), |
- settle_interval_seconds_(settle_interval_seconds), |
- reload_interval_minutes_(reload_interval_minutes) { |
- // Force an initial load, so GetPolicy() works. |
- policy_.reset(Load()); |
- DCHECK(policy_.get()); |
+ConfigDirPolicyProvider::ConfigDirPolicyProvider(const FilePath& config_dir) |
+ : config_dir_(config_dir) { |
} |
-void PolicyDirLoader::Stop() { |
- if (!ChromeThread::CurrentlyOn(ChromeThread::FILE)) { |
- ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, |
- NewRunnableMethod(this, &PolicyDirLoader::Stop)); |
- return; |
- } |
- |
- if (reload_task_) { |
- reload_task_->Cancel(); |
- reload_task_ = NULL; |
- } |
+bool ConfigDirPolicyProvider::Provide(ConfigurationPolicyStore* store) { |
+ scoped_ptr<DictionaryValue> policy(ReadPolicies()); |
+ DecodePolicyValueTree(policy.get(), store); |
+ return true; |
} |
-void PolicyDirLoader::Reload() { |
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
- |
- // Check the directory time in order to see whether a reload is required. |
- base::Time now = base::Time::Now(); |
- base::TimeDelta delay; |
- if (!IsSafeToReloadPolicy(now, &delay)) { |
- ScheduleReloadTask(delay); |
- return; |
- } |
- |
- // Load the policy definitions. |
- scoped_ptr<DictionaryValue> new_policy(Load()); |
- |
- // Check again in case the directory has changed while reading it. |
- if (!IsSafeToReloadPolicy(now, &delay)) { |
- ScheduleReloadTask(delay); |
- return; |
- } |
- |
- // Replace policy definition. |
- bool changed = false; |
- { |
- AutoLock lock(lock_); |
- changed = !policy_->Equals(new_policy.get()); |
- policy_.reset(new_policy.release()); |
- } |
- |
- // There's a change, report it! |
- if (changed) { |
- LOG(INFO) << "Policy reload from " << config_dir_.value() << " succeeded."; |
- origin_loop_->PostTask(FROM_HERE, |
- NewRunnableMethod(this, &PolicyDirLoader::NotifyPolicyChanged)); |
- } |
- |
- // As a safeguard in case the file watcher fails, schedule a reload task |
- // that'll make us recheck after a reasonable interval. |
- ScheduleReloadTask(base::TimeDelta::FromMinutes(reload_interval_minutes_)); |
-} |
- |
-DictionaryValue* PolicyDirLoader::GetPolicy() { |
- AutoLock lock(lock_); |
- return static_cast<DictionaryValue*>(policy_->DeepCopy()); |
-} |
- |
-void PolicyDirLoader::OnFilePathChanged(const FilePath& path) { |
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
- Reload(); |
-} |
- |
-void PolicyDirLoader::OnError() { |
- LOG(ERROR) << "FileWatcher on " << config_dir_.value() << " failed."; |
-} |
- |
-DictionaryValue* PolicyDirLoader::Load() { |
+DictionaryValue* ConfigDirPolicyProvider::ReadPolicies() { |
// Enumerate the files and sort them lexicographically. |
std::set<FilePath> files; |
file_util::FileEnumerator file_enumerator(config_dir_, false, |
@@ -143,105 +56,6 @@ |
return policy; |
} |
-bool PolicyDirLoader::IsSafeToReloadPolicy(const base::Time& now, |
- base::TimeDelta* delay) { |
- DCHECK(delay); |
- file_util::FileInfo dir_info; |
- |
- // Reading an empty directory or a file is always safe. |
- if (!file_util::GetFileInfo(config_dir_, &dir_info) || |
- !dir_info.is_directory) { |
- return true; |
- } |
- |
- // Check for too recent changes. |
- base::TimeDelta settleInterval( |
- base::TimeDelta::FromSeconds(settle_interval_seconds_)); |
- base::TimeDelta age = now - dir_info.last_modified; |
- if (age < settleInterval) { |
- *delay = settleInterval - age; |
- return false; |
- } |
- |
- return true; |
-} |
- |
-void PolicyDirLoader::ScheduleReloadTask(const base::TimeDelta& delay) { |
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
- |
- if (reload_task_) |
- reload_task_->Cancel(); |
- |
- reload_task_ = NewRunnableMethod(this, &PolicyDirLoader::ReloadFromTask); |
- ChromeThread::PostDelayedTask(ChromeThread::FILE, FROM_HERE, reload_task_, |
- delay.InMilliseconds()); |
-} |
- |
-void PolicyDirLoader::NotifyPolicyChanged() { |
- DCHECK_EQ(origin_loop_, MessageLoop::current()); |
- if (provider_) |
- provider_->NotifyStoreOfPolicyChange(); |
-} |
- |
-void PolicyDirLoader::ReloadFromTask() { |
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::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(); |
-} |
- |
-// PolicyDirWatcher implementation: |
- |
-void PolicyDirWatcher::Init(PolicyDirLoader* loader) { |
- // Initialization can happen early when the file thread is not yet available. |
- // So post a task to ourselves on th UI thread which will run after threading |
- // is up and schedule watch initialization on the file thread. |
- ChromeThread::PostTask(ChromeThread::UI, FROM_HERE, |
- NewRunnableMethod(this, |
- &PolicyDirWatcher::InitWatcher, |
- scoped_refptr<PolicyDirLoader>(loader))); |
-} |
- |
-void PolicyDirWatcher::InitWatcher( |
- const scoped_refptr<PolicyDirLoader>& loader) { |
- if (!ChromeThread::CurrentlyOn(ChromeThread::FILE)) { |
- ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, |
- NewRunnableMethod(this, &PolicyDirWatcher::InitWatcher, loader)); |
- return; |
- } |
- |
- if (!Watch(loader->config_dir(), loader.get())) |
- loader->OnError(); |
- |
- // There might have been changes to the directory in the time between |
- // construction of the loader and initialization of the watcher. Call reload |
- // to detect if that is the case. |
- loader->Reload(); |
-} |
- |
-// ConfigDirPolicyProvider implementation: |
- |
-ConfigDirPolicyProvider::ConfigDirPolicyProvider(const FilePath& config_dir) { |
- loader_ = new PolicyDirLoader(AsWeakPtr(), config_dir, kSettleIntervalSeconds, |
- kReloadIntervalMinutes); |
- watcher_ = new PolicyDirWatcher; |
- watcher_->Init(loader_.get()); |
-} |
- |
-ConfigDirPolicyProvider::~ConfigDirPolicyProvider() { |
- loader_->Stop(); |
-} |
- |
-bool ConfigDirPolicyProvider::Provide(ConfigurationPolicyStore* store) { |
- scoped_ptr<DictionaryValue> policy(loader_->GetPolicy()); |
- DCHECK(policy.get()); |
- DecodePolicyValueTree(policy.get(), store); |
- return true; |
-} |
- |
void ConfigDirPolicyProvider::DecodePolicyValueTree( |
DictionaryValue* policies, |
ConfigurationPolicyStore* store) { |
@@ -257,3 +71,4 @@ |
// TODO(mnissler): Handle preference overrides once |ConfigurationPolicyStore| |
// supports it. |
} |
+ |