Index: chrome/browser/policy/asynchronous_policy_loader.cc |
diff --git a/chrome/browser/policy/asynchronous_policy_loader.cc b/chrome/browser/policy/asynchronous_policy_loader.cc |
index e78c9aaf82c26fc01a3e94fb81f0e752bf5660a0..cf6706629e407e4de1806dc41c734c2476387003 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 |