| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2012 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/async_policy_loader.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "chrome/browser/policy/policy_bundle.h" |
| 9 #include "content/public/browser/browser_thread.h" |
| 10 |
| 11 using base::Time; |
| 12 using base::TimeDelta; |
| 13 using content::BrowserThread; |
| 14 |
| 15 namespace policy { |
| 16 |
| 17 namespace { |
| 18 |
| 19 // Amount of time to wait for the files on disk to settle before trying to load |
| 20 // them. This alleviates the problem of reading partially written files and |
| 21 // makes it possible to batch quasi-simultaneous changes. |
| 22 const int kSettleIntervalSeconds = 5; |
| 23 |
| 24 // The time interval for rechecking policy. This is the fallback in case the |
| 25 // implementation never detects changes. |
| 26 const int kReloadIntervalSeconds = 15 * 60; |
| 27 |
| 28 } // namespace |
| 29 |
| 30 AsyncPolicyLoader::AsyncPolicyLoader() |
| 31 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {} |
| 32 |
| 33 AsyncPolicyLoader::~AsyncPolicyLoader() { |
| 34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 35 } |
| 36 |
| 37 base::Time AsyncPolicyLoader::LastModificationTime() { |
| 38 return base::Time(); |
| 39 } |
| 40 |
| 41 void AsyncPolicyLoader::Reload(bool force) { |
| 42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 43 |
| 44 TimeDelta delay; |
| 45 Time now = Time::Now(); |
| 46 // Check if there was a recent modification to the underlying files. |
| 47 if (!force && !IsSafeToReload(now, &delay)) { |
| 48 ScheduleNextReload(delay); |
| 49 return; |
| 50 } |
| 51 |
| 52 scoped_ptr<PolicyBundle> bundle(Load()); |
| 53 |
| 54 // Check if there was a modification while reading. |
| 55 if (!force && !IsSafeToReload(now, &delay)) { |
| 56 ScheduleNextReload(delay); |
| 57 return; |
| 58 } |
| 59 |
| 60 update_callback_.Run(bundle.Pass()); |
| 61 ScheduleNextReload(TimeDelta::FromSeconds(kReloadIntervalSeconds)); |
| 62 } |
| 63 |
| 64 scoped_ptr<PolicyBundle> AsyncPolicyLoader::InitialLoad() { |
| 65 // This is the first load, early during startup. Use this to record the |
| 66 // initial |last_modification_time_|, so that potential changes made before |
| 67 // installing the watches can be detected. |
| 68 last_modification_time_ = LastModificationTime(); |
| 69 return Load(); |
| 70 } |
| 71 |
| 72 void AsyncPolicyLoader::Init(const UpdateCallback& update_callback) { |
| 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 74 DCHECK(update_callback_.is_null()); |
| 75 DCHECK(!update_callback.is_null()); |
| 76 update_callback_ = update_callback; |
| 77 |
| 78 InitOnFile(); |
| 79 |
| 80 // There might have been changes to the underlying files since the initial |
| 81 // load and before the watchers have been created. |
| 82 if (LastModificationTime() != last_modification_time_) |
| 83 Reload(false); |
| 84 |
| 85 // Start periodic refreshes. |
| 86 ScheduleNextReload(TimeDelta::FromSeconds(kReloadIntervalSeconds)); |
| 87 } |
| 88 |
| 89 void AsyncPolicyLoader::ScheduleNextReload(TimeDelta delay) { |
| 90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 91 weak_factory_.InvalidateWeakPtrs(); |
| 92 BrowserThread::PostDelayedTask( |
| 93 BrowserThread::FILE, FROM_HERE, |
| 94 base::Bind(&AsyncPolicyLoader::Reload, |
| 95 weak_factory_.GetWeakPtr(), |
| 96 false /* force */), |
| 97 delay); |
| 98 } |
| 99 |
| 100 bool AsyncPolicyLoader::IsSafeToReload(const Time& now, TimeDelta* delay) { |
| 101 Time last_modification = LastModificationTime(); |
| 102 if (last_modification.is_null()) |
| 103 return true; |
| 104 |
| 105 // If there was a change since the last recorded modification, wait some more. |
| 106 const TimeDelta kSettleInterval( |
| 107 TimeDelta::FromSeconds(kSettleIntervalSeconds)); |
| 108 if (last_modification != last_modification_time_) { |
| 109 last_modification_time_ = last_modification; |
| 110 last_modification_clock_ = now; |
| 111 *delay = kSettleInterval; |
| 112 return false; |
| 113 } |
| 114 |
| 115 // Check whether the settle interval has elapsed. |
| 116 const base::TimeDelta age = now - last_modification_clock_; |
| 117 if (age < kSettleInterval) { |
| 118 *delay = kSettleInterval - age; |
| 119 return false; |
| 120 } |
| 121 |
| 122 return true; |
| 123 } |
| 124 |
| 125 } // namespace policy |
| OLD | NEW |