• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/policy/asynchronous_policy_loader.h"
6 
7 #include "base/message_loop.h"
8 #include "base/task.h"
9 #include "content/browser/browser_thread.h"
10 
11 namespace policy {
12 
AsynchronousPolicyLoader(AsynchronousPolicyProvider::Delegate * delegate,int reload_interval_minutes)13 AsynchronousPolicyLoader::AsynchronousPolicyLoader(
14     AsynchronousPolicyProvider::Delegate* delegate,
15     int reload_interval_minutes)
16     : delegate_(delegate),
17       reload_task_(NULL),
18       reload_interval_(base::TimeDelta::FromMinutes(reload_interval_minutes)),
19       origin_loop_(MessageLoop::current()),
20       stopped_(false) {}
21 
Init()22 void AsynchronousPolicyLoader::Init() {
23   policy_.reset(delegate_->Load());
24   // Initialization can happen early when the file thread is not yet available,
25   // but the subclass of the loader must do some of their initialization on the
26   // file thread. Posting to the file thread directly before it is initialized
27   // will cause the task to be forgotten. Instead, post a task to the ui thread
28   // to delay the remainder of initialization until threading is fully
29   // initialized.
30   BrowserThread::PostTask(
31       BrowserThread::UI, FROM_HERE,
32       NewRunnableMethod(
33           this,
34           &AsynchronousPolicyLoader::InitAfterFileThreadAvailable));
35 }
36 
Stop()37 void AsynchronousPolicyLoader::Stop() {
38   if (!stopped_) {
39     stopped_ = true;
40     delegate_.reset();
41     FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
42                       observer_list_,
43                       OnProviderGoingAway());
44     BrowserThread::PostTask(
45         BrowserThread::FILE, FROM_HERE,
46         NewRunnableMethod(this, &AsynchronousPolicyLoader::StopOnFileThread));
47   }
48 }
49 
~AsynchronousPolicyLoader()50 AsynchronousPolicyLoader::~AsynchronousPolicyLoader() {
51 }
52 
53 // Manages the life cycle of a new policy map during until its life cycle is
54 // taken over by the policy loader.
55 class UpdatePolicyTask : public Task {
56  public:
UpdatePolicyTask(scoped_refptr<AsynchronousPolicyLoader> loader,DictionaryValue * new_policy)57   UpdatePolicyTask(scoped_refptr<AsynchronousPolicyLoader> loader,
58                    DictionaryValue* new_policy)
59       : loader_(loader),
60         new_policy_(new_policy) {}
61 
Run()62   virtual void Run() {
63     loader_->UpdatePolicy(new_policy_.release());
64   }
65 
66  private:
67   scoped_refptr<AsynchronousPolicyLoader> loader_;
68   scoped_ptr<DictionaryValue> new_policy_;
69   DISALLOW_COPY_AND_ASSIGN(UpdatePolicyTask);
70 };
71 
Reload()72 void AsynchronousPolicyLoader::Reload() {
73   if (delegate_.get()) {
74     DictionaryValue* new_policy = delegate_->Load();
75     PostUpdatePolicyTask(new_policy);
76   }
77 }
78 
AddObserver(ConfigurationPolicyProvider::Observer * observer)79 void AsynchronousPolicyLoader::AddObserver(
80     ConfigurationPolicyProvider::Observer* observer) {
81   observer_list_.AddObserver(observer);
82 }
83 
RemoveObserver(ConfigurationPolicyProvider::Observer * observer)84 void AsynchronousPolicyLoader::RemoveObserver(
85     ConfigurationPolicyProvider::Observer* observer) {
86   observer_list_.RemoveObserver(observer);
87 }
88 
CancelReloadTask()89 void AsynchronousPolicyLoader::CancelReloadTask() {
90   if (reload_task_) {
91     // Only check the thread if there's still a reload task. During
92     // destruction of unit tests, the message loop destruction can
93     // call this method when the file thread is no longer around,
94     // but in that case reload_task_ is NULL.
95     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
96     reload_task_->Cancel();
97     reload_task_ = NULL;
98   }
99 }
100 
ScheduleReloadTask(const base::TimeDelta & delay)101 void AsynchronousPolicyLoader::ScheduleReloadTask(
102     const base::TimeDelta& delay) {
103   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
104 
105   CancelReloadTask();
106 
107   reload_task_ =
108       NewRunnableMethod(this, &AsynchronousPolicyLoader::ReloadFromTask);
109   BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, reload_task_,
110                                  delay.InMilliseconds());
111 }
112 
ScheduleFallbackReloadTask()113 void AsynchronousPolicyLoader::ScheduleFallbackReloadTask() {
114   // As a safeguard in case that the load delegate failed to timely notice a
115   // change in policy, schedule a reload task that'll make us recheck after a
116   // reasonable interval.
117   ScheduleReloadTask(reload_interval_);
118 }
119 
ReloadFromTask()120 void AsynchronousPolicyLoader::ReloadFromTask() {
121   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
122 
123   // Drop the reference to the reload task, since the task might be the only
124   // referrer that keeps us alive, so we should not Cancel() it.
125   reload_task_ = NULL;
126 
127   Reload();
128 }
129 
InitOnFileThread()130 void AsynchronousPolicyLoader::InitOnFileThread() {
131 }
132 
StopOnFileThread()133 void AsynchronousPolicyLoader::StopOnFileThread() {
134   CancelReloadTask();
135 }
136 
PostUpdatePolicyTask(DictionaryValue * new_policy)137 void AsynchronousPolicyLoader::PostUpdatePolicyTask(
138     DictionaryValue* new_policy) {
139   origin_loop_->PostTask(FROM_HERE, new UpdatePolicyTask(this, new_policy));
140 }
141 
UpdatePolicy(DictionaryValue * new_policy_raw)142 void AsynchronousPolicyLoader::UpdatePolicy(DictionaryValue* new_policy_raw) {
143   scoped_ptr<DictionaryValue> new_policy(new_policy_raw);
144   DCHECK(policy_.get());
145   if (!policy_->Equals(new_policy.get())) {
146     policy_.reset(new_policy.release());
147     FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer,
148                       observer_list_,
149                       OnUpdatePolicy());
150   }
151 }
152 
InitAfterFileThreadAvailable()153 void AsynchronousPolicyLoader::InitAfterFileThreadAvailable() {
154   if (!stopped_) {
155     BrowserThread::PostTask(
156         BrowserThread::FILE, FROM_HERE,
157         NewRunnableMethod(this, &AsynchronousPolicyLoader::InitOnFileThread));
158   }
159 }
160 
161 }  // namespace policy
162