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/device_policy_cache.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/logging.h" | |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/metrics/histogram.h" | |
11 #include "base/values.h" | |
12 #include "chrome/browser/policy/cloud_policy_data_store.h" | |
13 #include "chrome/browser/policy/device_policy_decoder_chromeos.h" | |
14 #include "chrome/browser/policy/enterprise_install_attributes.h" | |
15 #include "chrome/browser/policy/enterprise_metrics.h" | |
16 #include "chrome/browser/policy/policy_map.h" | |
17 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" | |
18 #include "chrome/browser/policy/proto/device_management_backend.pb.h" | |
19 #include "chrome/browser/policy/proto/device_management_local.pb.h" | |
20 #include "google_apis/gaia/gaia_auth_util.h" | |
21 | |
22 namespace em = enterprise_management; | |
23 | |
24 namespace policy { | |
25 | |
26 DevicePolicyCache::DevicePolicyCache( | |
27 CloudPolicyDataStore* data_store, | |
28 EnterpriseInstallAttributes* install_attributes) | |
29 : data_store_(data_store), | |
30 install_attributes_(install_attributes), | |
31 device_settings_service_(chromeos::DeviceSettingsService::Get()), | |
32 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
33 policy_fetch_pending_(false) { | |
34 device_settings_service_->AddObserver(this); | |
35 } | |
36 | |
37 DevicePolicyCache::DevicePolicyCache( | |
38 CloudPolicyDataStore* data_store, | |
39 EnterpriseInstallAttributes* install_attributes, | |
40 chromeos::DeviceSettingsService* device_settings_service) | |
41 : data_store_(data_store), | |
42 install_attributes_(install_attributes), | |
43 device_settings_service_(device_settings_service), | |
44 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
45 policy_fetch_pending_(false) { | |
46 device_settings_service_->AddObserver(this); | |
47 } | |
48 | |
49 DevicePolicyCache::~DevicePolicyCache() { | |
50 device_settings_service_->RemoveObserver(this); | |
51 } | |
52 | |
53 void DevicePolicyCache::Load() { | |
54 DeviceSettingsUpdated(); | |
55 } | |
56 | |
57 bool DevicePolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) { | |
58 DCHECK(IsReady()); | |
59 | |
60 // Make sure we have an enterprise device. | |
61 std::string registration_domain(install_attributes_->GetDomain()); | |
62 if (registration_domain.empty()) { | |
63 LOG(WARNING) << "Refusing to accept policy on non-enterprise device."; | |
64 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, | |
65 kMetricPolicyFetchNonEnterpriseDevice, | |
66 kMetricPolicySize); | |
67 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
68 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
69 return false; | |
70 } | |
71 | |
72 // Check the user this policy is for against the device-locked name. | |
73 em::PolicyData policy_data; | |
74 if (!policy_data.ParseFromString(policy.policy_data())) { | |
75 LOG(WARNING) << "Invalid policy protobuf"; | |
76 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchInvalidPolicy, | |
77 kMetricPolicySize); | |
78 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
79 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
80 return false; | |
81 } | |
82 | |
83 // Existing installations may not have a canonicalized version of the | |
84 // registration domain in install attributes, so lower-case the data here. | |
85 if (registration_domain != gaia::ExtractDomainName(policy_data.username())) { | |
86 LOG(WARNING) << "Refusing policy blob for " << policy_data.username() | |
87 << " which doesn't match domain " << registration_domain; | |
88 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchUserMismatch, | |
89 kMetricPolicySize); | |
90 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
91 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
92 return false; | |
93 } | |
94 | |
95 set_last_policy_refresh_time(base::Time::NowFromSystemTime()); | |
96 | |
97 // Start a store operation. | |
98 policy_fetch_pending_ = true; | |
99 device_settings_service_->Store( | |
100 scoped_ptr<em::PolicyFetchResponse>(new em::PolicyFetchResponse(policy)), | |
101 base::Bind(&DevicePolicyCache::PolicyStoreOpCompleted, | |
102 weak_ptr_factory_.GetWeakPtr())); | |
103 return true; | |
104 } | |
105 | |
106 void DevicePolicyCache::SetUnmanaged() { | |
107 LOG(WARNING) << "Tried to set DevicePolicyCache to 'unmanaged'!"; | |
108 // This is not supported for DevicePolicyCache. | |
109 } | |
110 | |
111 void DevicePolicyCache::SetFetchingDone() { | |
112 // Don't send the notification just yet if there is a pending policy | |
113 // store/reload cycle. | |
114 if (!policy_fetch_pending_) | |
115 CloudPolicyCacheBase::SetFetchingDone(); | |
116 } | |
117 | |
118 void DevicePolicyCache::OwnershipStatusChanged() {} | |
119 | |
120 void DevicePolicyCache::DeviceSettingsUpdated() { | |
121 DCHECK(CalledOnValidThread()); | |
122 chromeos::DeviceSettingsService::Status status = | |
123 device_settings_service_->status(); | |
124 const em::PolicyData* policy_data = device_settings_service_->policy_data(); | |
125 if (status == chromeos::DeviceSettingsService::STORE_SUCCESS && | |
126 !policy_data) { | |
127 // Initial policy load is still pending. | |
128 return; | |
129 } | |
130 | |
131 if (!IsReady()) { | |
132 std::string device_token; | |
133 InstallInitialPolicy(status, policy_data, &device_token); | |
134 SetTokenAndFlagReady(device_token); | |
135 } else { // In other words, IsReady() == true | |
136 if (status != chromeos::DeviceSettingsService::STORE_SUCCESS || | |
137 !policy_data) { | |
138 if (status == chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR) { | |
139 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadSignature, | |
140 kMetricPolicySize); | |
141 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
142 CloudPolicySubsystem::SIGNATURE_MISMATCH); | |
143 } else { | |
144 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchOtherFailed, | |
145 kMetricPolicySize); | |
146 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
147 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
148 } | |
149 } else { | |
150 em::PolicyFetchResponse policy_response; | |
151 CHECK(policy_data->SerializeToString( | |
152 policy_response.mutable_policy_data())); | |
153 bool ok = SetPolicyInternal(policy_response, NULL, false); | |
154 if (ok) { | |
155 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchOK, | |
156 kMetricPolicySize); | |
157 } | |
158 } | |
159 } | |
160 } | |
161 | |
162 bool DevicePolicyCache::DecodePolicyData(const em::PolicyData& policy_data, | |
163 PolicyMap* policies) { | |
164 em::ChromeDeviceSettingsProto policy; | |
165 if (!policy.ParseFromString(policy_data.policy_value())) { | |
166 LOG(WARNING) << "Failed to parse ChromeDeviceSettingsProto."; | |
167 return false; | |
168 } | |
169 DecodeDevicePolicy(policy, policies, install_attributes_); | |
170 return true; | |
171 } | |
172 | |
173 void DevicePolicyCache::PolicyStoreOpCompleted() { | |
174 DCHECK(CalledOnValidThread()); | |
175 chromeos::DeviceSettingsService::Status status = | |
176 device_settings_service_->status(); | |
177 if (status != chromeos::DeviceSettingsService::STORE_SUCCESS) { | |
178 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyStoreFailed, | |
179 kMetricPolicySize); | |
180 if (status == chromeos::DeviceSettingsService::STORE_VALIDATION_ERROR) { | |
181 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchBadSignature, | |
182 kMetricPolicySize); | |
183 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
184 CloudPolicySubsystem::SIGNATURE_MISMATCH); | |
185 } else { | |
186 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyFetchOtherFailed, | |
187 kMetricPolicySize); | |
188 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
189 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
190 } | |
191 CheckFetchingDone(); | |
192 return; | |
193 } | |
194 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyStoreSucceeded, | |
195 kMetricPolicySize); | |
196 | |
197 CheckFetchingDone(); | |
198 } | |
199 | |
200 void DevicePolicyCache::InstallInitialPolicy( | |
201 chromeos::DeviceSettingsService::Status status, | |
202 const em::PolicyData* policy_data, | |
203 std::string* device_token) { | |
204 if (status == chromeos::DeviceSettingsService::STORE_NO_POLICY || | |
205 status == chromeos::DeviceSettingsService::STORE_KEY_UNAVAILABLE) { | |
206 InformNotifier(CloudPolicySubsystem::UNENROLLED, | |
207 CloudPolicySubsystem::NO_DETAILS); | |
208 return; | |
209 } | |
210 if (!policy_data) { | |
211 LOG(WARNING) << "Failed to parse PolicyData protobuf."; | |
212 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyLoadFailed, | |
213 kMetricPolicySize); | |
214 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
215 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
216 return; | |
217 } | |
218 if (!policy_data->has_request_token() || | |
219 policy_data->request_token().empty()) { | |
220 SetUnmanagedInternal(base::Time::NowFromSystemTime()); | |
221 InformNotifier(CloudPolicySubsystem::UNMANAGED, | |
222 CloudPolicySubsystem::NO_DETAILS); | |
223 // TODO(jkummerow): Reminder: When we want to feed device-wide settings | |
224 // made by a local owner into this cache, we need to call | |
225 // SetPolicyInternal() here. | |
226 return; | |
227 } | |
228 if (!policy_data->has_username() || !policy_data->has_device_id()) { | |
229 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyLoadFailed, | |
230 kMetricPolicySize); | |
231 InformNotifier(CloudPolicySubsystem::LOCAL_ERROR, | |
232 CloudPolicySubsystem::POLICY_LOCAL_ERROR); | |
233 return; | |
234 } | |
235 UMA_HISTOGRAM_ENUMERATION(kMetricPolicy, kMetricPolicyLoadSucceeded, | |
236 kMetricPolicySize); | |
237 data_store_->set_user_name(policy_data->username()); | |
238 data_store_->set_device_id(policy_data->device_id()); | |
239 *device_token = policy_data->request_token(); | |
240 base::Time timestamp; | |
241 em::PolicyFetchResponse policy_response; | |
242 CHECK(policy_data->SerializeToString(policy_response.mutable_policy_data())); | |
243 if (SetPolicyInternal(policy_response, ×tamp, true)) | |
244 set_last_policy_refresh_time(timestamp); | |
245 } | |
246 | |
247 void DevicePolicyCache::SetTokenAndFlagReady(const std::string& device_token) { | |
248 // We need to call SetDeviceToken unconditionally to indicate the cache has | |
249 // finished loading. | |
250 data_store_->SetDeviceToken(device_token, true); | |
251 SetReady(); | |
252 } | |
253 | |
254 void DevicePolicyCache::CheckFetchingDone() { | |
255 if (policy_fetch_pending_) { | |
256 CloudPolicyCacheBase::SetFetchingDone(); | |
257 policy_fetch_pending_ = false; | |
258 } | |
259 } | |
260 | |
261 } // namespace policy | |
OLD | NEW |