1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be 321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file. 421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/policy/file_based_policy_loader.h" 621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/compiler_specific.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h" 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing ::base::files::FilePathWatcher; 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace { 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Amount of time we wait for the files on disk to settle before trying to load 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// them. This alleviates the problem of reading partially written files and 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// makes it possible to batch quasi-simultaneous changes. 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst int kSettleIntervalSeconds = 5; 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// The time interval for rechecking policy. This is our fallback in case the 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// delegate never reports a change to the ReloadObserver. 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst int kReloadIntervalMinutes = 15; 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace policy { 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenFileBasedPolicyLoader::FileBasedPolicyLoader( 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FileBasedPolicyProvider::ProviderDelegate* provider_delegate) 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : AsynchronousPolicyLoader(provider_delegate, 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen kReloadIntervalMinutes), 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen config_file_path_(provider_delegate->config_file_path()), 3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen settle_interval_(base::TimeDelta::FromSeconds(kSettleIntervalSeconds)) { 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenFileBasedPolicyLoader::~FileBasedPolicyLoader() {} 3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass FileBasedPolicyWatcherDelegate : public FilePathWatcher::Delegate { 3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen explicit FileBasedPolicyWatcherDelegate( 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<FileBasedPolicyLoader> loader) 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : loader_(loader) {} 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual ~FileBasedPolicyWatcherDelegate() {} 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // FilePathWatcher::Delegate implementation: 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void OnFilePathChanged(const FilePath& path) OVERRIDE { 4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen loader_->OnFilePathChanged(path); 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void OnFilePathError(const FilePath& path) OVERRIDE { 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen loader_->OnFilePathError(path); 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_refptr<FileBasedPolicyLoader> loader_; 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DISALLOW_COPY_AND_ASSIGN(FileBasedPolicyWatcherDelegate); 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid FileBasedPolicyLoader::OnFilePathChanged( 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const FilePath& path) { 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Reload(); 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FileBasedPolicyLoader::OnFilePathError(const FilePath& path) { 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "FilePathWatcher on " << path.value() 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen << " failed."; 6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid FileBasedPolicyLoader::Reload() { 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!delegate()) 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Check the directory time in order to see whether a reload is required. 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::TimeDelta delay; 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::Time now = base::Time::Now(); 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!IsSafeToReloadPolicy(now, &delay)) { 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScheduleReloadTask(delay); 8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Load the policy definitions. 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen scoped_ptr<DictionaryValue> new_policy(delegate()->Load()); 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Check again in case the directory has changed while reading it. 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!IsSafeToReloadPolicy(now, &delay)) { 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScheduleReloadTask(delay); 8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PostUpdatePolicyTask(new_policy.release()); 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScheduleFallbackReloadTask(); 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid FileBasedPolicyLoader::InitOnFileThread() { 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen watcher_.reset(new FilePathWatcher); 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const FilePath& path = config_file_path(); 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!path.empty() && 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !watcher_->Watch(path, new FileBasedPolicyWatcherDelegate(this))) { 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnFilePathError(path); 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // There might have been changes to the directory in the time between 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // construction of the loader and initialization of the watcher. Call reload 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // to detect if that is the case. 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Reload(); 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ScheduleFallbackReloadTask(); 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid FileBasedPolicyLoader::StopOnFileThread() { 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen watcher_.reset(); 11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen AsynchronousPolicyLoader::StopOnFileThread(); 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool FileBasedPolicyLoader::IsSafeToReloadPolicy( 12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const base::Time& now, 12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::TimeDelta* delay) { 12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(delay); 12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // A null modification time indicates there's no data. 12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen FileBasedPolicyProvider::ProviderDelegate* provider_delegate = 12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen static_cast<FileBasedPolicyProvider::ProviderDelegate*>(delegate()); 12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::Time last_modification(provider_delegate->GetLastModification()); 12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (last_modification.is_null()) 12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // If there was a change since the last recorded modification, wait some more. 13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (last_modification != last_modification_file_) { 13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen last_modification_file_ = last_modification; 13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen last_modification_clock_ = now; 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *delay = settle_interval_; 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Check whether the settle interval has elapsed. 14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::TimeDelta age = now - last_modification_clock_; 14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (age < settle_interval_) { 14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *delay = settle_interval_ - age; 14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace policy 150