| 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/cloud_policy_refresh_scheduler.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/task_runner.h" | |
| 10 #include "chrome/browser/policy/cloud_policy_constants.h" | |
| 11 #include "chrome/common/chrome_notification_types.h" | |
| 12 #include "content/public/browser/notification_details.h" | |
| 13 | |
| 14 namespace policy { | |
| 15 | |
| 16 const int64 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs = | |
| 17 3 * 60 * 60 * 1000; // 3 hours. | |
| 18 const int64 CloudPolicyRefreshScheduler::kUnmanagedRefreshDelayMs = | |
| 19 24 * 60 * 60 * 1000; // 1 day. | |
| 20 const int64 CloudPolicyRefreshScheduler::kInitialErrorRetryDelayMs = | |
| 21 5 * 60 * 1000; // 5 minutes. | |
| 22 const int64 CloudPolicyRefreshScheduler::kRefreshDelayMinMs = | |
| 23 30 * 60 * 1000; // 30 minutes. | |
| 24 const int64 CloudPolicyRefreshScheduler::kRefreshDelayMaxMs = | |
| 25 24 * 60 * 60 * 1000; // 1 day. | |
| 26 | |
| 27 CloudPolicyRefreshScheduler::CloudPolicyRefreshScheduler( | |
| 28 CloudPolicyClient* client, | |
| 29 CloudPolicyStore* store, | |
| 30 const scoped_refptr<base::TaskRunner>& task_runner) | |
| 31 : client_(client), | |
| 32 store_(store), | |
| 33 task_runner_(task_runner), | |
| 34 error_retry_delay_ms_(kInitialErrorRetryDelayMs), | |
| 35 refresh_delay_ms_(kDefaultRefreshDelayMs) { | |
| 36 client_->AddObserver(this); | |
| 37 store_->AddObserver(this); | |
| 38 net::NetworkChangeNotifier::AddIPAddressObserver(this); | |
| 39 | |
| 40 UpdateLastRefreshFromPolicy(); | |
| 41 ScheduleRefresh(); | |
| 42 } | |
| 43 | |
| 44 CloudPolicyRefreshScheduler::~CloudPolicyRefreshScheduler() { | |
| 45 store_->RemoveObserver(this); | |
| 46 client_->RemoveObserver(this); | |
| 47 net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | |
| 48 } | |
| 49 | |
| 50 void CloudPolicyRefreshScheduler::SetRefreshDelay(int64 refresh_delay) { | |
| 51 refresh_delay_ms_ = std::min(std::max(refresh_delay, kRefreshDelayMinMs), | |
| 52 kRefreshDelayMaxMs); | |
| 53 ScheduleRefresh(); | |
| 54 } | |
| 55 | |
| 56 void CloudPolicyRefreshScheduler::OnPolicyFetched(CloudPolicyClient* client) { | |
| 57 error_retry_delay_ms_ = kInitialErrorRetryDelayMs; | |
| 58 | |
| 59 // Schedule the next refresh. | |
| 60 last_refresh_ = base::Time::NowFromSystemTime(); | |
| 61 ScheduleRefresh(); | |
| 62 } | |
| 63 | |
| 64 void CloudPolicyRefreshScheduler::OnRegistrationStateChanged( | |
| 65 CloudPolicyClient* client) { | |
| 66 error_retry_delay_ms_ = kInitialErrorRetryDelayMs; | |
| 67 | |
| 68 // The client might have registered, so trigger an immediate refresh. | |
| 69 last_refresh_ = base::Time(); | |
| 70 ScheduleRefresh(); | |
| 71 } | |
| 72 | |
| 73 void CloudPolicyRefreshScheduler::OnClientError(CloudPolicyClient* client) { | |
| 74 // Save the status for below. | |
| 75 DeviceManagementStatus status = client_->status(); | |
| 76 | |
| 77 // Schedule an error retry if applicable. | |
| 78 last_refresh_ = base::Time::NowFromSystemTime(); | |
| 79 ScheduleRefresh(); | |
| 80 | |
| 81 // Update the retry delay. | |
| 82 if (client->is_registered() && | |
| 83 (status == DM_STATUS_REQUEST_FAILED || | |
| 84 status == DM_STATUS_TEMPORARY_UNAVAILABLE)) { | |
| 85 error_retry_delay_ms_ = std::min(error_retry_delay_ms_ * 2, | |
| 86 refresh_delay_ms_); | |
| 87 } else { | |
| 88 error_retry_delay_ms_ = kInitialErrorRetryDelayMs; | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 void CloudPolicyRefreshScheduler::OnStoreLoaded(CloudPolicyStore* store) { | |
| 93 UpdateLastRefreshFromPolicy(); | |
| 94 | |
| 95 // Re-schedule the next refresh in case the is_managed bit changed. | |
| 96 ScheduleRefresh(); | |
| 97 } | |
| 98 | |
| 99 void CloudPolicyRefreshScheduler::OnStoreError(CloudPolicyStore* store) { | |
| 100 // If |store_| fails, the is_managed bit that it provides may become stale. | |
| 101 // The best guess in that situation is to assume is_managed didn't change and | |
| 102 // continue using the stale information. Thus, no specific response to a store | |
| 103 // error is required. NB: Changes to is_managed fire OnStoreLoaded(). | |
| 104 } | |
| 105 | |
| 106 void CloudPolicyRefreshScheduler::OnIPAddressChanged() { | |
| 107 if (client_->status() == DM_STATUS_REQUEST_FAILED) | |
| 108 RefreshAfter(0); | |
| 109 } | |
| 110 | |
| 111 void CloudPolicyRefreshScheduler::UpdateLastRefreshFromPolicy() { | |
| 112 if (!last_refresh_.is_null()) | |
| 113 return; | |
| 114 | |
| 115 // If the client has already fetched policy, assume that happened recently. If | |
| 116 // that assumption ever breaks, the proper thing to do probably is to move the | |
| 117 // |last_refresh_| bookkeeping to CloudPolicyClient. | |
| 118 if (!client_->responses().empty()) { | |
| 119 last_refresh_ = base::Time::NowFromSystemTime(); | |
| 120 return; | |
| 121 } | |
| 122 | |
| 123 // If there is a cached non-managed response, make sure to only re-query the | |
| 124 // server after kUnmanagedRefreshDelayMs. NB: For existing policy, an | |
| 125 // immediate refresh is intentional. | |
| 126 if (store_->has_policy() && !store_->is_managed()) { | |
| 127 last_refresh_ = | |
| 128 base::Time::UnixEpoch() + | |
| 129 base::TimeDelta::FromMilliseconds(store_->policy()->timestamp()); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 void CloudPolicyRefreshScheduler::ScheduleRefresh() { | |
| 134 // If the client isn't registered, there is nothing to do. | |
| 135 if (!client_->is_registered()) { | |
| 136 refresh_callback_.Cancel(); | |
| 137 return; | |
| 138 } | |
| 139 | |
| 140 // If there is a registration, go by the client's status. That will tell us | |
| 141 // what the appropriate refresh delay should be. | |
| 142 switch (client_->status()) { | |
| 143 case DM_STATUS_SUCCESS: | |
| 144 if (store_->is_managed()) | |
| 145 RefreshAfter(refresh_delay_ms_); | |
| 146 else | |
| 147 RefreshAfter(kUnmanagedRefreshDelayMs); | |
| 148 return; | |
| 149 case DM_STATUS_SERVICE_ACTIVATION_PENDING: | |
| 150 case DM_STATUS_SERVICE_POLICY_NOT_FOUND: | |
| 151 RefreshAfter(refresh_delay_ms_); | |
| 152 return; | |
| 153 case DM_STATUS_REQUEST_FAILED: | |
| 154 case DM_STATUS_TEMPORARY_UNAVAILABLE: | |
| 155 RefreshAfter(error_retry_delay_ms_); | |
| 156 return; | |
| 157 case DM_STATUS_REQUEST_INVALID: | |
| 158 case DM_STATUS_HTTP_STATUS_ERROR: | |
| 159 case DM_STATUS_RESPONSE_DECODING_ERROR: | |
| 160 case DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED: | |
| 161 RefreshAfter(kUnmanagedRefreshDelayMs); | |
| 162 return; | |
| 163 case DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID: | |
| 164 case DM_STATUS_SERVICE_DEVICE_NOT_FOUND: | |
| 165 case DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER: | |
| 166 case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT: | |
| 167 case DM_STATUS_SERVICE_MISSING_LICENSES: | |
| 168 // Need a re-registration, no use in retrying. | |
| 169 return; | |
| 170 } | |
| 171 | |
| 172 NOTREACHED() << "Invalid client status " << client_->status(); | |
| 173 RefreshAfter(kUnmanagedRefreshDelayMs); | |
| 174 } | |
| 175 | |
| 176 void CloudPolicyRefreshScheduler::PerformRefresh() { | |
| 177 if (client_->is_registered()) { | |
| 178 // Update |last_refresh_| so another fetch isn't triggered inadvertently. | |
| 179 last_refresh_ = base::Time::NowFromSystemTime(); | |
| 180 | |
| 181 // The result of this operation will be reported through a callback, at | |
| 182 // which point the next refresh will be scheduled. | |
| 183 client_->FetchPolicy(); | |
| 184 return; | |
| 185 } | |
| 186 | |
| 187 // This should never happen, as the registration change should have been | |
| 188 // handled via OnRegistrationStateChanged(). | |
| 189 NOTREACHED(); | |
| 190 } | |
| 191 | |
| 192 void CloudPolicyRefreshScheduler::RefreshAfter(int delta_ms) { | |
| 193 base::TimeDelta delta(base::TimeDelta::FromMilliseconds(delta_ms)); | |
| 194 refresh_callback_.Cancel(); | |
| 195 | |
| 196 // Schedule the callback. | |
| 197 base::TimeDelta delay = | |
| 198 std::max((last_refresh_ + delta) - base::Time::NowFromSystemTime(), | |
| 199 base::TimeDelta()); | |
| 200 refresh_callback_.Reset( | |
| 201 base::Bind(&CloudPolicyRefreshScheduler::PerformRefresh, | |
| 202 base::Unretained(this))); | |
| 203 task_runner_->PostDelayedTask(FROM_HERE, refresh_callback_.callback(), delay); | |
| 204 } | |
| 205 | |
| 206 } // namespace policy | |
| OLD | NEW |