Chromium Code Reviews| Index: chrome/browser/policy/file_based_policy_provider.cc | 
| diff --git a/chrome/browser/policy/file_based_policy_provider.cc b/chrome/browser/policy/file_based_policy_provider.cc | 
| index 578277d61d78f22ce4e529f8adb1f972b75cb4b8..c913c9d2801574830d816d1d663a290d5b129937 100644 | 
| --- a/chrome/browser/policy/file_based_policy_provider.cc | 
| +++ b/chrome/browser/policy/file_based_policy_provider.cc | 
| @@ -14,146 +14,71 @@ | 
| #include "chrome/browser/browser_thread.h" | 
| #include "chrome/common/json_value_serializer.h" | 
| -namespace policy { | 
| +namespace { | 
| // Amount of time we wait for the files on disk 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 | 
| -// file path watch fails or doesn't report a change. | 
| -const int kReloadIntervalMinutes = 15; | 
| - | 
| -// FileBasedPolicyProvider implementation: | 
| - | 
| -FileBasedPolicyProvider::Delegate::~Delegate() { | 
| -} | 
| - | 
| -FileBasedPolicyProvider::Delegate::Delegate(const FilePath& config_file_path) | 
| - : config_file_path_(config_file_path) { | 
| -} | 
| - | 
| -FileBasedPolicyProvider::FileBasedPolicyProvider( | 
| - const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, | 
| - FileBasedPolicyProvider::Delegate* delegate) | 
| - : ConfigurationPolicyProvider(policy_list) { | 
| - loader_ = new FileBasedPolicyLoader(AsWeakPtr(), | 
| - delegate, | 
| - kSettleIntervalSeconds, | 
| - kReloadIntervalMinutes); | 
| - watcher_ = new FileBasedPolicyWatcher; | 
| - watcher_->Init(loader_.get()); | 
| -} | 
| - | 
| -FileBasedPolicyProvider::~FileBasedPolicyProvider() { | 
| - loader_->Stop(); | 
| -} | 
| - | 
| -bool FileBasedPolicyProvider::Provide( | 
| - ConfigurationPolicyStoreInterface* store) { | 
| - scoped_ptr<DictionaryValue> policy(loader_->GetPolicy()); | 
| - DCHECK(policy.get()); | 
| - DecodePolicyValueTree(policy.get(), store); | 
| - return true; | 
| -} | 
| - | 
| -// FileBasedPolicyLoader implementation: | 
| - | 
| -FileBasedPolicyLoader::FileBasedPolicyLoader( | 
| - base::WeakPtr<ConfigurationPolicyProvider> provider, | 
| - FileBasedPolicyProvider::Delegate* delegate, | 
| - int settle_interval_seconds, | 
| - int reload_interval_minutes) | 
| - : delegate_(delegate), | 
| - provider_(provider), | 
| - origin_loop_(MessageLoop::current()), | 
| - reload_task_(NULL), | 
| - settle_interval_seconds_(settle_interval_seconds), | 
| - reload_interval_minutes_(reload_interval_minutes) { | 
| - // Force an initial load, so GetPolicy() works. | 
| - policy_.reset(delegate_->Load()); | 
| - DCHECK(policy_.get()); | 
| } | 
| -void FileBasedPolicyLoader::Stop() { | 
| - if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 
| - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 
| - NewRunnableMethod(this, &FileBasedPolicyLoader::Stop)); | 
| - return; | 
| - } | 
| +namespace policy { | 
| - if (reload_task_) { | 
| - reload_task_->Cancel(); | 
| - reload_task_ = NULL; | 
| - } | 
| +FileBasedPolicyProvider::WatcherDelegate::WatcherDelegate( | 
| + const FilePath& config_file_path, | 
| + AsynchronousPolicyProvider::PolicyChangeObserver* observer) | 
| + : config_file_path_(config_file_path), | 
| + observer_(observer) { | 
| } | 
| -void FileBasedPolicyLoader::Reload() { | 
| +void FileBasedPolicyProvider::WatcherDelegate::Init() { | 
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| + watcher_.reset(new FilePathWatcher()); | 
| + if (!config_file_path_.empty() && | 
| + !watcher_->Watch(config_file_path_, this)) | 
| + OnError(); | 
| - // Check the directory time in order to see whether a reload is required. | 
| - base::TimeDelta delay; | 
| - base::Time now = base::Time::Now(); | 
| - if (!IsSafeToReloadPolicy(now, &delay)) { | 
| - ScheduleReloadTask(delay); | 
| - return; | 
| - } | 
| - | 
| - // Load the policy definitions. | 
| - scoped_ptr<DictionaryValue> new_policy(delegate_->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) { | 
| - VLOG(0) << "Policy reload from " << config_file_path().value() | 
| - << " succeeded."; | 
| - origin_loop_->PostTask(FROM_HERE, | 
| - NewRunnableMethod(this, &FileBasedPolicyLoader::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_)); | 
| + // 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. | 
| + observer_->OnPolicyChange(); | 
| } | 
| -DictionaryValue* FileBasedPolicyLoader::GetPolicy() { | 
| - AutoLock lock(lock_); | 
| - return static_cast<DictionaryValue*>(policy_->DeepCopy()); | 
| +void FileBasedPolicyProvider::WatcherDelegate::Stop() { | 
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| + watcher_.reset(NULL); | 
| + observer_.reset(NULL); | 
| 
 
Mattias Nissler (ping if slow)
2010/12/02 18:16:00
No need to pass the NULL literal, you can just use
 
danno
2010/12/03 17:05:38
Done.
 
 | 
| } | 
| -void FileBasedPolicyLoader::OnFilePathChanged(const FilePath& path) { | 
| +void FileBasedPolicyProvider::WatcherDelegate::OnFilePathChanged( | 
| + const FilePath& path) { | 
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 
| - Reload(); | 
| + if (observer_.get()) | 
| + observer_->OnPolicyChange(); | 
| } | 
| -void FileBasedPolicyLoader::OnError() { | 
| - LOG(ERROR) << "FilePathWatcher on " << config_file_path().value() | 
| +void FileBasedPolicyProvider::WatcherDelegate::OnError() { | 
| + LOG(ERROR) << "FilePathWatcher on " << config_file_path_.value() | 
| << " failed."; | 
| } | 
| -FileBasedPolicyLoader::~FileBasedPolicyLoader() { | 
| +FileBasedPolicyProvider::ProviderDelegate::ProviderDelegate( | 
| + const FilePath& config_file_path) | 
| + : config_file_path_(config_file_path), | 
| + settle_interval_seconds_(kSettleIntervalSeconds){ | 
| } | 
| -bool FileBasedPolicyLoader::IsSafeToReloadPolicy(const base::Time& now, | 
| - base::TimeDelta* delay) { | 
| +FileBasedPolicyProvider::ProviderDelegate::~ProviderDelegate() { | 
| +} | 
| + | 
| +bool FileBasedPolicyProvider::ProviderDelegate::IsSafeToReloadPolicy( | 
| + const base::Time& now, | 
| + base::TimeDelta* delay) { | 
| DCHECK(delay); | 
| // A null modification time indicates there's no data. | 
| - base::Time last_modification(delegate_->GetLastModification()); | 
| + base::Time last_modification(GetLastModification()); | 
| if (last_modification.is_null()) | 
| return true; | 
| @@ -177,68 +102,32 @@ bool FileBasedPolicyLoader::IsSafeToReloadPolicy(const base::Time& now, | 
| return true; | 
| } | 
| -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::NotifyPolicyChanged() { | 
| - DCHECK_EQ(origin_loop_, MessageLoop::current()); | 
| - if (provider_) | 
| - provider_->NotifyStoreOfPolicyChange(); | 
| -} | 
| - | 
| -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(); | 
| -} | 
| - | 
| -// FileBasedPolicyWatcher implementation: | 
| +void FileBasedPolicyProvider::ProviderDelegate::Init( | 
| + AsynchronousPolicyProvider::PolicyChangeObserver* observer) { | 
| + watcher_delegate_ = new FileBasedPolicyProvider::WatcherDelegate( | 
| + config_file_path_, | 
| + observer); | 
| -FileBasedPolicyWatcher::FileBasedPolicyWatcher() { | 
| + // Initialization can happen early when the file thread is not | 
| + // yet available. So post a task on the FILE thread which will run after | 
| + // threading is up and schedule watch initialization on the file thread. | 
| + BrowserThread::PostTask( | 
| + BrowserThread::FILE, FROM_HERE, | 
| + NewRunnableMethod(watcher_delegate_.get(), | 
| + &FileBasedPolicyProvider::WatcherDelegate::Init)); | 
| } | 
| -void FileBasedPolicyWatcher::Init(FileBasedPolicyLoader* loader) { | 
| - // Initialization can happen early when the file thread is not yet available. | 
| - // So post a task to ourselves on the UI thread which will run after threading | 
| - // is up and schedule watch initialization on the file thread. | 
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 
| - NewRunnableMethod(this, | 
| - &FileBasedPolicyWatcher::InitWatcher, | 
| - scoped_refptr<FileBasedPolicyLoader>(loader))); | 
| +void FileBasedPolicyProvider::ProviderDelegate::Stop() { | 
| + BrowserThread::PostTask( | 
| + BrowserThread::FILE, FROM_HERE, | 
| + NewRunnableMethod(watcher_delegate_.get(), | 
| + &FileBasedPolicyProvider::WatcherDelegate::Stop)); | 
| } | 
| -FileBasedPolicyWatcher::~FileBasedPolicyWatcher() { | 
| -} | 
| - | 
| -void FileBasedPolicyWatcher::InitWatcher( | 
| - const scoped_refptr<FileBasedPolicyLoader>& loader) { | 
| - if (!BrowserThread::CurrentlyOn(BrowserThread::FILE)) { | 
| - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 
| - NewRunnableMethod(this, &FileBasedPolicyWatcher::InitWatcher, loader)); | 
| - return; | 
| - } | 
| - | 
| - if (!loader->config_file_path().empty() && | 
| - !watcher_.Watch(loader->config_file_path(), 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(); | 
| +FileBasedPolicyProvider::FileBasedPolicyProvider( | 
| + const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list, | 
| + FileBasedPolicyProvider::ProviderDelegate* delegate) | 
| + : AsynchronousPolicyProvider(policy_list, delegate) { | 
| } | 
| } // namespace policy |