Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: chrome/browser/policy/file_based_policy_loader.cc

Issue 5562002: Refactor FileBasedPolicyProvider, introduce AsynchronousPolicyProvider. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more unit test fixes Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/file_based_policy_loader.h"
6
7 namespace {
8
9 // Amount of time we wait for the files on disk to settle before trying to load
10 // them. This alleviates the problem of reading partially written files and
11 // makes it possible to batch quasi-simultaneous changes.
12 const int kSettleIntervalSeconds = 5;
13
14 // The time interval for rechecking policy. This is our fallback in case the
15 // delegate never reports a change to the ReloadObserver.
16 const int kReloadIntervalMinutes = 15;
17
18 }
19
20 namespace policy {
21
22 FileBasedPolicyLoader::FileBasedPolicyLoader(
23 FileBasedPolicyProvider::ProviderDelegate* provider_delegate)
24 : AsynchronousPolicyLoader(provider_delegate),
25 config_file_path_(provider_delegate->config_file_path()),
26 reload_task_(NULL),
27 reload_interval_(base::TimeDelta::FromMinutes(kReloadIntervalMinutes)),
28 settle_interval_(base::TimeDelta::FromSeconds(kSettleIntervalSeconds)) {
29 }
30
31 class FileBasedPolicyWatcherDelegate : public FilePathWatcher::Delegate {
32 public:
33 explicit FileBasedPolicyWatcherDelegate(
34 scoped_refptr<FileBasedPolicyLoader> loader)
35 : loader_(loader) {}
36 virtual ~FileBasedPolicyWatcherDelegate() {}
37
38 // FilePathWatcher::Delegate implementation:
39 void OnFilePathChanged(const FilePath& path) {
40 loader_->OnFilePathChanged(path);
41 }
42
43 void OnError() {
44 loader_->OnError();
45 }
46
47 private:
48 scoped_refptr<FileBasedPolicyLoader> loader_;
49 DISALLOW_COPY_AND_ASSIGN(FileBasedPolicyWatcherDelegate);
50 };
51
52 void FileBasedPolicyLoader::Init() {
53 AsynchronousPolicyLoader::Init();
54
55 // Initialization can happen early when the file thread is not yet available,
56 // but the watcher's initialization must be done on the file thread. Posting
57 // to a to the file directly before the file thread is initialized will cause
58 // the task to be forgotten. Instead, post a task to the ui thread to delay
59 // the remainder of initialization until threading is fully initialized.
60 BrowserThread::PostTask(
61 BrowserThread::FILE, FROM_HERE,
62 NewRunnableMethod(this,
63 &FileBasedPolicyLoader::InitAfterIOThreadAvailable));
64 }
65
66 void FileBasedPolicyLoader::Stop() {
67 AsynchronousPolicyLoader::Stop();
68 BrowserThread::PostTask(
69 BrowserThread::FILE, FROM_HERE,
70 NewRunnableMethod(this, &FileBasedPolicyLoader::StopOnFileThread));
71 }
72
73 void FileBasedPolicyLoader::OnFilePathChanged(
74 const FilePath& path) {
75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
76 Reload();
77 }
78
79 void FileBasedPolicyLoader::OnError() {
80 LOG(ERROR) << "FilePathWatcher on " << config_file_path().value()
81 << " failed.";
82 }
83
84 void FileBasedPolicyLoader::Reload() {
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
86
87 if (!delegate())
88 return;
89
90 // Check the directory time in order to see whether a reload is required.
91 base::TimeDelta delay;
92 base::Time now = base::Time::Now();
93 if (!IsSafeToReloadPolicy(now, &delay)) {
94 ScheduleReloadTask(delay);
95 return;
96 }
97
98 // Load the policy definitions.
99 scoped_ptr<DictionaryValue> new_policy(delegate()->Load());
100
101 // Check again in case the directory has changed while reading it.
102 if (!IsSafeToReloadPolicy(now, &delay)) {
103 ScheduleReloadTask(delay);
104 return;
105 }
106
107 PostUpdatePolicyTask(new_policy.release());
108
109 ScheduleFallbackReloadTask();
110 }
111
112 void FileBasedPolicyLoader::InitAfterIOThreadAvailable() {
113 BrowserThread::PostTask(
114 BrowserThread::FILE, FROM_HERE,
115 NewRunnableMethod(this, &FileBasedPolicyLoader::InitWatcher));
116
117 ScheduleFallbackReloadTask();
118 }
119
120 void FileBasedPolicyLoader::InitWatcher() {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
122 watcher_.reset(new FilePathWatcher);
123 if (!config_file_path().empty() &&
124 !watcher_->Watch(config_file_path(),
125 new FileBasedPolicyWatcherDelegate(this))) {
126 OnError();
127 }
128
129 // There might have been changes to the directory in the time between
130 // construction of the loader and initialization of the watcher. Call reload
131 // to detect if that is the case.
132 Reload();
133 }
134
135 void FileBasedPolicyLoader::StopOnFileThread() {
136 watcher_.reset();
137 if (reload_task_) {
138 reload_task_->Cancel();
139 reload_task_ = NULL;
140 }
141 }
142
143 void FileBasedPolicyLoader::ScheduleReloadTask(
144 const base::TimeDelta& delay) {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
146
147 if (reload_task_)
148 reload_task_->Cancel();
149
150 reload_task_ =
151 NewRunnableMethod(this, &FileBasedPolicyLoader::ReloadFromTask);
152 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, reload_task_,
153 delay.InMilliseconds());
154 }
155
156 void FileBasedPolicyLoader::ScheduleFallbackReloadTask() {
157 // As a safeguard in case that the load delegate failed to timely notice a
158 // change in policy, schedule a reload task that'll make us recheck after a
159 // reasonable interval.
160 ScheduleReloadTask(reload_interval_);
161 }
162
163 void FileBasedPolicyLoader::ReloadFromTask() {
164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
165
166 // Drop the reference to the reload task, since the task might be the only
167 // referer that keeps us alive, so we should not Cancel() it.
168 reload_task_ = NULL;
169
170 Reload();
171 }
172
173 bool FileBasedPolicyLoader::IsSafeToReloadPolicy(
174 const base::Time& now,
175 base::TimeDelta* delay) {
176 DCHECK(delay);
177
178 // A null modification time indicates there's no data.
179 FileBasedPolicyProvider::ProviderDelegate* provider_delegate =
180 static_cast<FileBasedPolicyProvider::ProviderDelegate*>(delegate());
181 base::Time last_modification(provider_delegate->GetLastModification());
182 if (last_modification.is_null())
183 return true;
184
185 // If there was a change since the last recorded modification, wait some more.
186 if (last_modification != last_modification_file_) {
187 last_modification_file_ = last_modification;
188 last_modification_clock_ = now;
189 *delay = settle_interval_;
190 return false;
191 }
192
193 // Check whether the settle interval has elapsed.
194 base::TimeDelta age = now - last_modification_clock_;
195 if (age < settle_interval_) {
196 *delay = settle_interval_ - age;
197 return false;
198 }
199
200 return true;
201 }
202
203 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698