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/chromeos/device_settings_provider.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/callback.h" | |
10 #include "base/file_util.h" | |
11 #include "base/logging.h" | |
12 #include "base/string_util.h" | |
13 #include "base/threading/thread_restrictions.h" | |
14 #include "base/values.h" | |
15 #include "chrome/browser/browser_process.h" | |
16 #include "chrome/browser/chromeos/cros/cros_library.h" | |
17 #include "chrome/browser/chromeos/cros/network_library.h" | |
18 #include "chrome/browser/chromeos/cros_settings.h" | |
19 #include "chrome/browser/chromeos/cros_settings_names.h" | |
20 #include "chrome/browser/chromeos/login/signed_settings_cache.h" | |
21 #include "chrome/browser/chromeos/login/signed_settings_helper.h" | |
22 #include "chrome/browser/chromeos/login/user_manager.h" | |
23 #include "chrome/browser/policy/app_pack_updater.h" | |
24 #include "chrome/browser/policy/browser_policy_connector.h" | |
25 #include "chrome/browser/policy/cloud_policy_constants.h" | |
26 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" | |
27 #include "chrome/browser/ui/options/options_util.h" | |
28 #include "chrome/common/chrome_notification_types.h" | |
29 #include "chrome/installer/util/google_update_settings.h" | |
30 #include "content/public/browser/notification_service.h" | |
31 | |
32 using google::protobuf::RepeatedPtrField; | |
33 | |
34 namespace em = enterprise_management; | |
35 | |
36 namespace chromeos { | |
37 | |
38 namespace { | |
39 | |
40 // List of settings handled by the DeviceSettingsProvider. | |
41 const char* kKnownSettings[] = { | |
42 kAccountsPrefAllowGuest, | |
43 kAccountsPrefAllowNewUser, | |
44 kAccountsPrefEphemeralUsersEnabled, | |
45 kAccountsPrefShowUserNamesOnSignIn, | |
46 kAccountsPrefUsers, | |
47 kAppPack, | |
48 kDeviceOwner, | |
49 kIdleLogoutTimeout, | |
50 kIdleLogoutWarningDuration, | |
51 kPolicyMissingMitigationMode, | |
52 kReleaseChannel, | |
53 kReleaseChannelDelegated, | |
54 kReportDeviceActivityTimes, | |
55 kReportDeviceBootMode, | |
56 kReportDeviceLocation, | |
57 kReportDeviceVersionInfo, | |
58 kScreenSaverExtensionId, | |
59 kScreenSaverTimeout, | |
60 kSettingProxyEverywhere, | |
61 kSignedDataRoamingEnabled, | |
62 kStartUpUrls, | |
63 kStatsReportingPref, | |
64 }; | |
65 | |
66 // Upper bound for number of retries to fetch a signed setting. | |
67 static const int kNumRetriesLimit = 9; | |
68 | |
69 // Legacy policy file location. Used to detect migration from pre v12 ChromeOS. | |
70 const char kLegacyPolicyFile[] = "/var/lib/whitelist/preferences"; | |
71 | |
72 bool IsControlledSetting(const std::string& pref_path) { | |
73 const char** end = kKnownSettings + arraysize(kKnownSettings); | |
74 return std::find(kKnownSettings, end, pref_path) != end; | |
75 } | |
76 | |
77 bool HasOldMetricsFile() { | |
78 // TODO(pastarmovj): Remove this once migration is not needed anymore. | |
79 // If the value is not set we should try to migrate legacy consent file. | |
80 // Loading consent file state causes us to do blocking IO on UI thread. | |
81 // Temporarily allow it until we fix http://crbug.com/62626 | |
82 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
83 return GoogleUpdateSettings::GetCollectStatsConsent(); | |
84 } | |
85 | |
86 } // namespace | |
87 | |
88 DeviceSettingsProvider::DeviceSettingsProvider( | |
89 const NotifyObserversCallback& notify_cb, | |
90 SignedSettingsHelper* signed_settings_helper) | |
91 : CrosSettingsProvider(notify_cb), | |
92 signed_settings_helper_(signed_settings_helper), | |
93 ownership_status_(OwnershipService::GetSharedInstance()->GetStatus(true)), | |
94 migration_helper_(new SignedSettingsMigrationHelper()), | |
95 retries_left_(kNumRetriesLimit), | |
96 trusted_status_(TEMPORARILY_UNTRUSTED) { | |
97 // Register for notification when ownership is taken so that we can update | |
98 // the |ownership_status_| and reload if needed. | |
99 registrar_.Add(this, chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED, | |
100 content::NotificationService::AllSources()); | |
101 // Make sure we have at least the cache data immediately. | |
102 RetrieveCachedData(); | |
103 // Start prefetching preferences. | |
104 Reload(); | |
105 } | |
106 | |
107 DeviceSettingsProvider::~DeviceSettingsProvider() { | |
108 } | |
109 | |
110 void DeviceSettingsProvider::Reload() { | |
111 // While fetching we can't trust the cache anymore. | |
112 trusted_status_ = TEMPORARILY_UNTRUSTED; | |
113 if (ownership_status_ == OwnershipService::OWNERSHIP_NONE) { | |
114 RetrieveCachedData(); | |
115 } else { | |
116 // Retrieve the real data. | |
117 signed_settings_helper_->StartRetrievePolicyOp( | |
118 base::Bind(&DeviceSettingsProvider::OnRetrievePolicyCompleted, | |
119 base::Unretained(this))); | |
120 } | |
121 } | |
122 | |
123 void DeviceSettingsProvider::DoSet(const std::string& path, | |
124 const base::Value& in_value) { | |
125 if (!UserManager::Get()->IsCurrentUserOwner() && | |
126 ownership_status_ != OwnershipService::OWNERSHIP_NONE) { | |
127 LOG(WARNING) << "Changing settings from non-owner, setting=" << path; | |
128 | |
129 // Revert UI change. | |
130 NotifyObservers(path); | |
131 return; | |
132 } | |
133 | |
134 if (IsControlledSetting(path)) { | |
135 pending_changes_.push_back(PendingQueueElement(path, in_value.DeepCopy())); | |
136 if (pending_changes_.size() == 1) | |
137 SetInPolicy(); | |
138 } else { | |
139 NOTREACHED() << "Try to set unhandled cros setting " << path; | |
140 } | |
141 } | |
142 | |
143 void DeviceSettingsProvider::Observe( | |
144 int type, | |
145 const content::NotificationSource& source, | |
146 const content::NotificationDetails& details) { | |
147 if (type == chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) { | |
148 // Reload the policy blob once the owner key has been loaded or updated. | |
149 ownership_status_ = OwnershipService::OWNERSHIP_TAKEN; | |
150 Reload(); | |
151 } | |
152 } | |
153 | |
154 const em::PolicyData DeviceSettingsProvider::policy() const { | |
155 return policy_; | |
156 } | |
157 | |
158 void DeviceSettingsProvider::RetrieveCachedData() { | |
159 // If there is no owner yet, this function will pull the policy cache from the | |
160 // temp storage and use that instead. | |
161 em::PolicyData policy; | |
162 if (!signed_settings_cache::Retrieve(&policy, | |
163 g_browser_process->local_state())) { | |
164 VLOG(1) << "Can't retrieve temp store possibly not created yet."; | |
165 // Prepare empty data for the case we don't have temp cache yet. | |
166 policy.set_policy_type(kDevicePolicyType); | |
167 em::ChromeDeviceSettingsProto pol; | |
168 policy.set_policy_value(pol.SerializeAsString()); | |
169 } | |
170 | |
171 policy_ = policy; | |
172 UpdateValuesCache(); | |
173 } | |
174 | |
175 void DeviceSettingsProvider::SetInPolicy() { | |
176 if (pending_changes_.empty()) { | |
177 NOTREACHED(); | |
178 return; | |
179 } | |
180 | |
181 const std::string& prop = pending_changes_[0].first; | |
182 base::Value* value = pending_changes_[0].second; | |
183 if (prop == kDeviceOwner) { | |
184 // Just store it in the memory cache without trusted checks or persisting. | |
185 std::string owner; | |
186 if (value->GetAsString(&owner)) { | |
187 policy_.set_username(owner); | |
188 // In this case the |value_cache_| takes the ownership of |value|. | |
189 values_cache_.SetValue(prop, value); | |
190 NotifyObservers(prop); | |
191 // We can't trust this value anymore until we reload the real username. | |
192 trusted_status_ = TEMPORARILY_UNTRUSTED; | |
193 pending_changes_.erase(pending_changes_.begin()); | |
194 if (!pending_changes_.empty()) | |
195 SetInPolicy(); | |
196 } else { | |
197 NOTREACHED(); | |
198 } | |
199 return; | |
200 } | |
201 | |
202 if (RequestTrustedEntity() != TRUSTED) { | |
203 // Otherwise we should first reload and apply on top of that. | |
204 signed_settings_helper_->StartRetrievePolicyOp( | |
205 base::Bind(&DeviceSettingsProvider::FinishSetInPolicy, | |
206 base::Unretained(this))); | |
207 return; | |
208 } | |
209 | |
210 trusted_status_ = TEMPORARILY_UNTRUSTED; | |
211 em::PolicyData data = policy(); | |
212 em::ChromeDeviceSettingsProto pol; | |
213 pol.ParseFromString(data.policy_value()); | |
214 if (prop == kAccountsPrefAllowNewUser) { | |
215 em::AllowNewUsersProto* allow = pol.mutable_allow_new_users(); | |
216 bool allow_value; | |
217 if (value->GetAsBoolean(&allow_value)) | |
218 allow->set_allow_new_users(allow_value); | |
219 else | |
220 NOTREACHED(); | |
221 } else if (prop == kAccountsPrefAllowGuest) { | |
222 em::GuestModeEnabledProto* guest = pol.mutable_guest_mode_enabled(); | |
223 bool guest_value; | |
224 if (value->GetAsBoolean(&guest_value)) | |
225 guest->set_guest_mode_enabled(guest_value); | |
226 else | |
227 NOTREACHED(); | |
228 } else if (prop == kAccountsPrefShowUserNamesOnSignIn) { | |
229 em::ShowUserNamesOnSigninProto* show = pol.mutable_show_user_names(); | |
230 bool show_value; | |
231 if (value->GetAsBoolean(&show_value)) | |
232 show->set_show_user_names(show_value); | |
233 else | |
234 NOTREACHED(); | |
235 } else if (prop == kSignedDataRoamingEnabled) { | |
236 em::DataRoamingEnabledProto* roam = pol.mutable_data_roaming_enabled(); | |
237 bool roaming_value = false; | |
238 if (value->GetAsBoolean(&roaming_value)) | |
239 roam->set_data_roaming_enabled(roaming_value); | |
240 else | |
241 NOTREACHED(); | |
242 ApplyRoamingSetting(roaming_value); | |
243 } else if (prop == kSettingProxyEverywhere) { | |
244 // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed. | |
245 std::string proxy_value; | |
246 if (value->GetAsString(&proxy_value)) { | |
247 bool success = | |
248 pol.mutable_device_proxy_settings()->ParseFromString(proxy_value); | |
249 DCHECK(success); | |
250 } else { | |
251 NOTREACHED(); | |
252 } | |
253 } else if (prop == kReleaseChannel) { | |
254 em::ReleaseChannelProto* release_channel = pol.mutable_release_channel(); | |
255 std::string channel_value; | |
256 if (value->GetAsString(&channel_value)) | |
257 release_channel->set_release_channel(channel_value); | |
258 else | |
259 NOTREACHED(); | |
260 } else if (prop == kStatsReportingPref) { | |
261 em::MetricsEnabledProto* metrics = pol.mutable_metrics_enabled(); | |
262 bool metrics_value = false; | |
263 if (value->GetAsBoolean(&metrics_value)) | |
264 metrics->set_metrics_enabled(metrics_value); | |
265 else | |
266 NOTREACHED(); | |
267 ApplyMetricsSetting(false, metrics_value); | |
268 } else if (prop == kAccountsPrefUsers) { | |
269 em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist(); | |
270 whitelist_proto->clear_user_whitelist(); | |
271 base::ListValue& users = static_cast<base::ListValue&>(*value); | |
272 for (base::ListValue::const_iterator i = users.begin(); | |
273 i != users.end(); ++i) { | |
274 std::string email; | |
275 if ((*i)->GetAsString(&email)) | |
276 whitelist_proto->add_user_whitelist(email.c_str()); | |
277 } | |
278 } else if (prop == kAccountsPrefEphemeralUsersEnabled) { | |
279 em::EphemeralUsersEnabledProto* ephemeral_users_enabled = | |
280 pol.mutable_ephemeral_users_enabled(); | |
281 bool ephemeral_users_enabled_value = false; | |
282 if (value->GetAsBoolean(&ephemeral_users_enabled_value)) | |
283 ephemeral_users_enabled->set_ephemeral_users_enabled( | |
284 ephemeral_users_enabled_value); | |
285 else | |
286 NOTREACHED(); | |
287 } else { | |
288 // The remaining settings don't support Set(), since they are not | |
289 // intended to be customizable by the user: | |
290 // kAppPack | |
291 // kIdleLogoutTimeout | |
292 // kIdleLogoutWarningDuration | |
293 // kReleaseChannelDelegated | |
294 // kReportDeviceVersionInfo | |
295 // kReportDeviceActivityTimes | |
296 // kReportDeviceBootMode | |
297 // kReportDeviceLocation | |
298 // kScreenSaverExtensionId | |
299 // kScreenSaverTimeout | |
300 // kStartUpUrls | |
301 | |
302 NOTREACHED(); | |
303 } | |
304 data.set_policy_value(pol.SerializeAsString()); | |
305 // Set the cache to the updated value. | |
306 policy_ = data; | |
307 UpdateValuesCache(); | |
308 | |
309 if (!signed_settings_cache::Store(data, g_browser_process->local_state())) | |
310 LOG(ERROR) << "Couldn't store to the temp storage."; | |
311 | |
312 if (ownership_status_ == OwnershipService::OWNERSHIP_TAKEN) { | |
313 em::PolicyFetchResponse policy_envelope; | |
314 policy_envelope.set_policy_data(policy_.SerializeAsString()); | |
315 signed_settings_helper_->StartStorePolicyOp( | |
316 policy_envelope, | |
317 base::Bind(&DeviceSettingsProvider::OnStorePolicyCompleted, | |
318 base::Unretained(this))); | |
319 } else { | |
320 // OnStorePolicyCompleted won't get called in this case so proceed with any | |
321 // pending operations immediately. | |
322 delete pending_changes_[0].second; | |
323 pending_changes_.erase(pending_changes_.begin()); | |
324 if (!pending_changes_.empty()) | |
325 SetInPolicy(); | |
326 } | |
327 } | |
328 | |
329 void DeviceSettingsProvider::FinishSetInPolicy( | |
330 SignedSettings::ReturnCode code, | |
331 const em::PolicyFetchResponse& policy) { | |
332 if (code != SignedSettings::SUCCESS) { | |
333 LOG(ERROR) << "Can't serialize to policy error code: " << code; | |
334 Reload(); | |
335 return; | |
336 } | |
337 // Update the internal caches and set the trusted flag to true so that we | |
338 // can pass the trustedness check in the second call to SetInPolicy. | |
339 OnRetrievePolicyCompleted(code, policy); | |
340 | |
341 SetInPolicy(); | |
342 } | |
343 | |
344 void DeviceSettingsProvider::DecodeLoginPolicies( | |
345 const em::ChromeDeviceSettingsProto& policy, | |
346 PrefValueMap* new_values_cache) const { | |
347 // For all our boolean settings the following is applicable: | |
348 // true is default permissive value and false is safe prohibitive value. | |
349 // Exceptions: | |
350 // kSignedDataRoamingEnabled has a default value of false. | |
351 // kAccountsPrefEphemeralUsersEnabled has a default value of false. | |
352 if (policy.has_allow_new_users() && | |
353 policy.allow_new_users().has_allow_new_users() && | |
354 policy.allow_new_users().allow_new_users()) { | |
355 // New users allowed, user_whitelist() ignored. | |
356 new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true); | |
357 } else if (!policy.has_user_whitelist()) { | |
358 // If we have the allow_new_users bool, and it is true, we honor that above. | |
359 // In all other cases (don't have it, have it and it is set to false, etc), | |
360 // We will honor the user_whitelist() if it is there and populated. | |
361 // Otherwise we default to allowing new users. | |
362 new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true); | |
363 } else { | |
364 new_values_cache->SetBoolean( | |
365 kAccountsPrefAllowNewUser, | |
366 policy.user_whitelist().user_whitelist_size() == 0); | |
367 } | |
368 | |
369 new_values_cache->SetBoolean( | |
370 kAccountsPrefAllowGuest, | |
371 !policy.has_guest_mode_enabled() || | |
372 !policy.guest_mode_enabled().has_guest_mode_enabled() || | |
373 policy.guest_mode_enabled().guest_mode_enabled()); | |
374 | |
375 new_values_cache->SetBoolean( | |
376 kAccountsPrefShowUserNamesOnSignIn, | |
377 !policy.has_show_user_names() || | |
378 !policy.show_user_names().has_show_user_names() || | |
379 policy.show_user_names().show_user_names()); | |
380 | |
381 new_values_cache->SetBoolean( | |
382 kAccountsPrefEphemeralUsersEnabled, | |
383 policy.has_ephemeral_users_enabled() && | |
384 policy.ephemeral_users_enabled().has_ephemeral_users_enabled() && | |
385 policy.ephemeral_users_enabled().ephemeral_users_enabled()); | |
386 | |
387 base::ListValue* list = new base::ListValue(); | |
388 const em::UserWhitelistProto& whitelist_proto = policy.user_whitelist(); | |
389 const RepeatedPtrField<std::string>& whitelist = | |
390 whitelist_proto.user_whitelist(); | |
391 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin(); | |
392 it != whitelist.end(); ++it) { | |
393 list->Append(base::Value::CreateStringValue(*it)); | |
394 } | |
395 new_values_cache->SetValue(kAccountsPrefUsers, list); | |
396 } | |
397 | |
398 void DeviceSettingsProvider::DecodeKioskPolicies( | |
399 const em::ChromeDeviceSettingsProto& policy, | |
400 PrefValueMap* new_values_cache) const { | |
401 if (policy.has_forced_logout_timeouts()) { | |
402 if (policy.forced_logout_timeouts().has_idle_logout_timeout()) { | |
403 new_values_cache->SetInteger( | |
404 kIdleLogoutTimeout, | |
405 policy.forced_logout_timeouts().idle_logout_timeout()); | |
406 } | |
407 | |
408 if (policy.forced_logout_timeouts().has_idle_logout_warning_duration()) { | |
409 new_values_cache->SetInteger( | |
410 kIdleLogoutWarningDuration, | |
411 policy.forced_logout_timeouts().idle_logout_warning_duration()); | |
412 } | |
413 } | |
414 | |
415 if (policy.has_login_screen_saver()) { | |
416 if (policy.login_screen_saver().has_screen_saver_timeout()) { | |
417 new_values_cache->SetInteger( | |
418 kScreenSaverTimeout, | |
419 policy.login_screen_saver().screen_saver_timeout()); | |
420 } | |
421 | |
422 if (policy.login_screen_saver().has_screen_saver_extension_id()) { | |
423 new_values_cache->SetString( | |
424 kScreenSaverExtensionId, | |
425 policy.login_screen_saver().screen_saver_extension_id()); | |
426 } | |
427 } | |
428 | |
429 if (policy.has_app_pack()) { | |
430 typedef RepeatedPtrField<em::AppPackEntryProto> proto_type; | |
431 base::ListValue* list = new base::ListValue; | |
432 const proto_type& app_pack = policy.app_pack().app_pack(); | |
433 for (proto_type::const_iterator it = app_pack.begin(); | |
434 it != app_pack.end(); ++it) { | |
435 base::DictionaryValue* entry = new base::DictionaryValue; | |
436 if (it->has_extension_id()) { | |
437 entry->SetString(policy::AppPackUpdater::kExtensionId, | |
438 it->extension_id()); | |
439 } | |
440 if (it->has_update_url()) | |
441 entry->SetString(policy::AppPackUpdater::kUpdateUrl, it->update_url()); | |
442 list->Append(entry); | |
443 } | |
444 new_values_cache->SetValue(kAppPack, list); | |
445 } | |
446 | |
447 if (policy.has_start_up_urls()) { | |
448 base::ListValue* list = new base::ListValue(); | |
449 const em::StartUpUrlsProto& urls_proto = policy.start_up_urls(); | |
450 const RepeatedPtrField<std::string>& urls = urls_proto.start_up_urls(); | |
451 for (RepeatedPtrField<std::string>::const_iterator it = urls.begin(); | |
452 it != urls.end(); ++it) { | |
453 list->Append(base::Value::CreateStringValue(*it)); | |
454 } | |
455 new_values_cache->SetValue(kStartUpUrls, list); | |
456 } | |
457 } | |
458 | |
459 void DeviceSettingsProvider::DecodeNetworkPolicies( | |
460 const em::ChromeDeviceSettingsProto& policy, | |
461 PrefValueMap* new_values_cache) const { | |
462 new_values_cache->SetBoolean( | |
463 kSignedDataRoamingEnabled, | |
464 policy.has_data_roaming_enabled() && | |
465 policy.data_roaming_enabled().has_data_roaming_enabled() && | |
466 policy.data_roaming_enabled().data_roaming_enabled()); | |
467 | |
468 // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed. | |
469 std::string serialized; | |
470 if (policy.has_device_proxy_settings() && | |
471 policy.device_proxy_settings().SerializeToString(&serialized)) { | |
472 new_values_cache->SetString(kSettingProxyEverywhere, serialized); | |
473 } | |
474 } | |
475 | |
476 void DeviceSettingsProvider::DecodeReportingPolicies( | |
477 const em::ChromeDeviceSettingsProto& policy, | |
478 PrefValueMap* new_values_cache) const { | |
479 if (policy.has_device_reporting()) { | |
480 if (policy.device_reporting().has_report_version_info()) { | |
481 new_values_cache->SetBoolean( | |
482 kReportDeviceVersionInfo, | |
483 policy.device_reporting().report_version_info()); | |
484 } | |
485 if (policy.device_reporting().has_report_activity_times()) { | |
486 new_values_cache->SetBoolean( | |
487 kReportDeviceActivityTimes, | |
488 policy.device_reporting().report_activity_times()); | |
489 } | |
490 if (policy.device_reporting().has_report_boot_mode()) { | |
491 new_values_cache->SetBoolean( | |
492 kReportDeviceBootMode, | |
493 policy.device_reporting().report_boot_mode()); | |
494 } | |
495 // Device location reporting needs to pass privacy review before it can be | |
496 // enabled. crosbug.com/24681 | |
497 // if (policy.device_reporting().has_report_location()) { | |
498 // new_values_cache->SetBoolean( | |
499 // kReportDeviceLocation, | |
500 // policy.device_reporting().report_location()); | |
501 // } | |
502 } | |
503 } | |
504 | |
505 void DeviceSettingsProvider::DecodeGenericPolicies( | |
506 const em::ChromeDeviceSettingsProto& policy, | |
507 PrefValueMap* new_values_cache) const { | |
508 if (policy.has_metrics_enabled()) { | |
509 new_values_cache->SetBoolean(kStatsReportingPref, | |
510 policy.metrics_enabled().metrics_enabled()); | |
511 } else { | |
512 new_values_cache->SetBoolean(kStatsReportingPref, HasOldMetricsFile()); | |
513 } | |
514 | |
515 if (!policy.has_release_channel() || | |
516 !policy.release_channel().has_release_channel()) { | |
517 // Default to an invalid channel (will be ignored). | |
518 new_values_cache->SetString(kReleaseChannel, ""); | |
519 } else { | |
520 new_values_cache->SetString(kReleaseChannel, | |
521 policy.release_channel().release_channel()); | |
522 } | |
523 | |
524 new_values_cache->SetBoolean( | |
525 kReleaseChannelDelegated, | |
526 policy.has_release_channel() && | |
527 policy.release_channel().has_release_channel_delegated() && | |
528 policy.release_channel().release_channel_delegated()); | |
529 } | |
530 | |
531 void DeviceSettingsProvider::UpdateValuesCache() { | |
532 const em::PolicyData data = policy(); | |
533 PrefValueMap new_values_cache; | |
534 | |
535 if (data.has_username() && !data.has_request_token()) | |
536 new_values_cache.SetString(kDeviceOwner, data.username()); | |
537 | |
538 em::ChromeDeviceSettingsProto pol; | |
539 pol.ParseFromString(data.policy_value()); | |
540 | |
541 DecodeLoginPolicies(pol, &new_values_cache); | |
542 DecodeKioskPolicies(pol, &new_values_cache); | |
543 DecodeNetworkPolicies(pol, &new_values_cache); | |
544 DecodeReportingPolicies(pol, &new_values_cache); | |
545 DecodeGenericPolicies(pol, &new_values_cache); | |
546 | |
547 // Collect all notifications but send them only after we have swapped the | |
548 // cache so that if somebody actually reads the cache will be already valid. | |
549 std::vector<std::string> notifications; | |
550 // Go through the new values and verify in the old ones. | |
551 PrefValueMap::iterator iter = new_values_cache.begin(); | |
552 for (; iter != new_values_cache.end(); ++iter) { | |
553 const base::Value* old_value; | |
554 if (!values_cache_.GetValue(iter->first, &old_value) || | |
555 !old_value->Equals(iter->second)) { | |
556 notifications.push_back(iter->first); | |
557 } | |
558 } | |
559 // Now check for values that have been removed from the policy blob. | |
560 for (iter = values_cache_.begin(); iter != values_cache_.end(); ++iter) { | |
561 const base::Value* value; | |
562 if (!new_values_cache.GetValue(iter->first, &value)) | |
563 notifications.push_back(iter->first); | |
564 } | |
565 // Swap and notify. | |
566 values_cache_.Swap(&new_values_cache); | |
567 for (size_t i = 0; i < notifications.size(); ++i) | |
568 NotifyObservers(notifications[i]); | |
569 } | |
570 | |
571 void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file, | |
572 bool new_value) const { | |
573 // TODO(pastarmovj): Remove this once migration is not needed anymore. | |
574 // If the value is not set we should try to migrate legacy consent file. | |
575 if (use_file) { | |
576 new_value = HasOldMetricsFile(); | |
577 // Make sure the values will get eventually written to the policy file. | |
578 migration_helper_->AddMigrationValue( | |
579 kStatsReportingPref, base::Value::CreateBooleanValue(new_value)); | |
580 migration_helper_->MigrateValues(); | |
581 LOG(INFO) << "No metrics policy set will revert to checking " | |
582 << "consent file which is " | |
583 << (new_value ? "on." : "off."); | |
584 } | |
585 VLOG(1) << "Metrics policy is being set to : " << new_value | |
586 << "(use file : " << use_file << ")"; | |
587 // TODO(pastarmovj): Remove this once we don't need to regenerate the | |
588 // consent file for the GUID anymore. | |
589 OptionsUtil::ResolveMetricsReportingEnabled(new_value); | |
590 } | |
591 | |
592 void DeviceSettingsProvider::ApplyRoamingSetting(bool new_value) const { | |
593 NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); | |
594 const NetworkDevice* cellular = cros->FindCellularDevice(); | |
595 if (cellular) { | |
596 bool device_value = cellular->data_roaming_allowed(); | |
597 if (!device_value && cros->IsCellularAlwaysInRoaming()) { | |
598 // If operator requires roaming always enabled, ignore supplied value | |
599 // and set data roaming allowed in true always. | |
600 cros->SetCellularDataRoamingAllowed(true); | |
601 } else if (device_value != new_value) { | |
602 cros->SetCellularDataRoamingAllowed(new_value); | |
603 } | |
604 } | |
605 } | |
606 | |
607 void DeviceSettingsProvider::ApplySideEffects() const { | |
608 const em::PolicyData data = policy(); | |
609 em::ChromeDeviceSettingsProto pol; | |
610 pol.ParseFromString(data.policy_value()); | |
611 // First migrate metrics settings as needed. | |
612 if (pol.has_metrics_enabled()) | |
613 ApplyMetricsSetting(false, pol.metrics_enabled().metrics_enabled()); | |
614 else | |
615 ApplyMetricsSetting(true, false); | |
616 // Next set the roaming setting as needed. | |
617 ApplyRoamingSetting(pol.has_data_roaming_enabled() ? | |
618 pol.data_roaming_enabled().data_roaming_enabled() : false); | |
619 } | |
620 | |
621 bool DeviceSettingsProvider::MitigateMissingPolicy() { | |
622 // First check if the device has been owned already and if not exit | |
623 // immediately. | |
624 if (g_browser_process->browser_policy_connector()->GetDeviceMode() != | |
625 policy::DEVICE_MODE_CONSUMER) { | |
626 return false; | |
627 } | |
628 | |
629 // If we are here the policy file were corrupted or missing. This can happen | |
630 // because we are migrating Pre R11 device to the new secure policies or there | |
631 // was an attempt to circumvent policy system. In this case we should populate | |
632 // the policy cache with "safe-mode" defaults which should allow the owner to | |
633 // log in but lock the device for anyone else until the policy blob has been | |
634 // recreated by the session manager. | |
635 LOG(ERROR) << "Corruption of the policy data has been detected." | |
636 << "Switching to \"safe-mode\" policies until the owner logs in " | |
637 << "to regenerate the policy data."; | |
638 values_cache_.SetBoolean(kAccountsPrefAllowNewUser, true); | |
639 values_cache_.SetBoolean(kAccountsPrefAllowGuest, true); | |
640 values_cache_.SetBoolean(kPolicyMissingMitigationMode, true); | |
641 trusted_status_ = TRUSTED; | |
642 // Make sure we will recreate the policy once the owner logs in. | |
643 // Any value not in this list will be left to the default which is fine as | |
644 // we repopulate the whitelist with the owner and all other existing users | |
645 // every time the owner enables whitelist filtering on the UI. | |
646 migration_helper_->AddMigrationValue( | |
647 kAccountsPrefAllowNewUser, base::Value::CreateBooleanValue(true)); | |
648 migration_helper_->MigrateValues(); | |
649 return true; | |
650 } | |
651 | |
652 const base::Value* DeviceSettingsProvider::Get(const std::string& path) const { | |
653 if (IsControlledSetting(path)) { | |
654 const base::Value* value; | |
655 if (values_cache_.GetValue(path, &value)) | |
656 return value; | |
657 } else { | |
658 NOTREACHED() << "Trying to get non cros setting."; | |
659 } | |
660 | |
661 return NULL; | |
662 } | |
663 | |
664 DeviceSettingsProvider::TrustedStatus | |
665 DeviceSettingsProvider::PrepareTrustedValues(const base::Closure& cb) { | |
666 TrustedStatus status = RequestTrustedEntity(); | |
667 if (status == TEMPORARILY_UNTRUSTED && !cb.is_null()) | |
668 callbacks_.push_back(cb); | |
669 return status; | |
670 } | |
671 | |
672 bool DeviceSettingsProvider::HandlesSetting(const std::string& path) const { | |
673 return IsControlledSetting(path); | |
674 } | |
675 | |
676 DeviceSettingsProvider::TrustedStatus | |
677 DeviceSettingsProvider::RequestTrustedEntity() { | |
678 if (ownership_status_ == OwnershipService::OWNERSHIP_NONE) | |
679 return TRUSTED; | |
680 return trusted_status_; | |
681 } | |
682 | |
683 void DeviceSettingsProvider::OnStorePolicyCompleted( | |
684 SignedSettings::ReturnCode code) { | |
685 // In any case reload the policy cache to now. | |
686 if (code != SignedSettings::SUCCESS) | |
687 Reload(); | |
688 else | |
689 trusted_status_ = TRUSTED; | |
690 | |
691 // Clear the finished task and proceed with any other stores that could be | |
692 // pending by now. | |
693 delete pending_changes_[0].second; | |
694 pending_changes_.erase(pending_changes_.begin()); | |
695 if (!pending_changes_.empty()) | |
696 SetInPolicy(); | |
697 } | |
698 | |
699 void DeviceSettingsProvider::OnRetrievePolicyCompleted( | |
700 SignedSettings::ReturnCode code, | |
701 const em::PolicyFetchResponse& policy_data) { | |
702 VLOG(1) << "OnRetrievePolicyCompleted. Error code: " << code | |
703 << ", trusted status : " << trusted_status_ | |
704 << ", ownership status : " << ownership_status_; | |
705 switch (code) { | |
706 case SignedSettings::SUCCESS: { | |
707 DCHECK(policy_data.has_policy_data()); | |
708 policy_.ParseFromString(policy_data.policy_data()); | |
709 signed_settings_cache::Store(policy(), | |
710 g_browser_process->local_state()); | |
711 UpdateValuesCache(); | |
712 trusted_status_ = TRUSTED; | |
713 // TODO(pastarmovj): Make those side effects responsibility of the | |
714 // respective subsystems. | |
715 ApplySideEffects(); | |
716 break; | |
717 } | |
718 case SignedSettings::NOT_FOUND: | |
719 if (MitigateMissingPolicy()) | |
720 break; | |
721 case SignedSettings::KEY_UNAVAILABLE: { | |
722 if (ownership_status_ != OwnershipService::OWNERSHIP_TAKEN) | |
723 NOTREACHED() << "No policies present yet, will use the temp storage."; | |
724 trusted_status_ = PERMANENTLY_UNTRUSTED; | |
725 break; | |
726 } | |
727 case SignedSettings::BAD_SIGNATURE: | |
728 case SignedSettings::OPERATION_FAILED: { | |
729 LOG(ERROR) << "Failed to retrieve cros policies. Reason:" << code; | |
730 if (retries_left_ > 0) { | |
731 trusted_status_ = TEMPORARILY_UNTRUSTED; | |
732 retries_left_ -= 1; | |
733 Reload(); | |
734 return; | |
735 } | |
736 LOG(ERROR) << "No retries left"; | |
737 trusted_status_ = PERMANENTLY_UNTRUSTED; | |
738 break; | |
739 } | |
740 } | |
741 // Notify the observers we are done. | |
742 std::vector<base::Closure> callbacks; | |
743 callbacks.swap(callbacks_); | |
744 for (size_t i = 0; i < callbacks.size(); ++i) | |
745 callbacks[i].Run(); | |
746 } | |
747 | |
748 } // namespace chromeos | |
OLD | NEW |