Chromium Code Reviews

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: merge with TOT Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | | 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::InitAfterFileThreadAvailable));
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::InitAfterFileThreadAvailable() {
113 if (provider()) {
114 BrowserThread::PostTask(
115 BrowserThread::FILE, FROM_HERE,
116 NewRunnableMethod(this, &FileBasedPolicyLoader::InitWatcher));
117
118 ScheduleFallbackReloadTask();
119 }
120 }
121
122 void FileBasedPolicyLoader::InitWatcher() {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
124 watcher_.reset(new FilePathWatcher);
125 if (!config_file_path().empty() &&
126 !watcher_->Watch(config_file_path(),
127 new FileBasedPolicyWatcherDelegate(this))) {
128 OnError();
129 }
130
131 // There might have been changes to the directory in the time between
132 // construction of the loader and initialization of the watcher. Call reload
133 // to detect if that is the case.
134 Reload();
135 }
136
137 void FileBasedPolicyLoader::StopOnFileThread() {
138 watcher_.reset();
139 if (reload_task_) {
140 reload_task_->Cancel();
141 reload_task_ = NULL;
142 }
143 }
144
145 void FileBasedPolicyLoader::ScheduleReloadTask(
146 const base::TimeDelta& delay) {
147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
148
149 if (reload_task_)
150 reload_task_->Cancel();
151
152 reload_task_ =
153 NewRunnableMethod(this, &FileBasedPolicyLoader::ReloadFromTask);
154 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, reload_task_,
155 delay.InMilliseconds());
156 }
157
158 void FileBasedPolicyLoader::ScheduleFallbackReloadTask() {
159 // As a safeguard in case that the load delegate failed to timely notice a
160 // change in policy, schedule a reload task that'll make us recheck after a
161 // reasonable interval.
162 ScheduleReloadTask(reload_interval_);
163 }
164
165 void FileBasedPolicyLoader::ReloadFromTask() {
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
167
168 // Drop the reference to the reload task, since the task might be the only
169 // referer that keeps us alive, so we should not Cancel() it.
170 reload_task_ = NULL;
171
172 Reload();
173 }
174
175 bool FileBasedPolicyLoader::IsSafeToReloadPolicy(
176 const base::Time& now,
177 base::TimeDelta* delay) {
178 DCHECK(delay);
179
180 // A null modification time indicates there's no data.
181 FileBasedPolicyProvider::ProviderDelegate* provider_delegate =
182 static_cast<FileBasedPolicyProvider::ProviderDelegate*>(delegate());
183 base::Time last_modification(provider_delegate->GetLastModification());
184 if (last_modification.is_null())
185 return true;
186
187 // If there was a change since the last recorded modification, wait some more.
188 if (last_modification != last_modification_file_) {
189 last_modification_file_ = last_modification;
190 last_modification_clock_ = now;
191 *delay = settle_interval_;
192 return false;
193 }
194
195 // Check whether the settle interval has elapsed.
196 base::TimeDelta age = now - last_modification_clock_;
197 if (age < settle_interval_) {
198 *delay = settle_interval_ - age;
199 return false;
200 }
201
202 return true;
203 }
204
205 } // namespace policy
OLDNEW
« no previous file with comments | « chrome/browser/policy/file_based_policy_loader.h ('k') | chrome/browser/policy/file_based_policy_provider.h » ('j') | no next file with comments »

Powered by Google App Engine