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/settings/device_settings_provider.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/callback.h"
10 #include "base/logging.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.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/policy/browser_policy_connector_chromeos.h"
17 #include "chrome/browser/chromeos/policy/device_local_account.h"
18 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
19 #include "chrome/browser/chromeos/settings/cros_settings.h"
20 #include "chrome/browser/chromeos/settings/device_settings_cache.h"
21 #include "chrome/browser/metrics/metrics_reporting_state.h"
22 #include "chrome/installer/util/google_update_settings.h"
23 #include "chromeos/chromeos_switches.h"
24 #include "chromeos/dbus/cryptohome_client.h"
25 #include "chromeos/dbus/dbus_thread_manager.h"
26 #include "chromeos/settings/cros_settings_names.h"
27 #include "policy/proto/device_management_backend.pb.h"
28
29 using google::protobuf::RepeatedField;
30 using google::protobuf::RepeatedPtrField;
31
32 namespace em = enterprise_management;
33
34 namespace chromeos {
35
36 namespace {
37
38 // List of settings handled by the DeviceSettingsProvider.
39 const char* kKnownSettings[] = {
40 kAccountsPrefAllowGuest,
41 kAccountsPrefAllowNewUser,
42 kAccountsPrefDeviceLocalAccounts,
43 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled,
44 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
45 kAccountsPrefDeviceLocalAccountAutoLoginId,
46 kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
47 kAccountsPrefEphemeralUsersEnabled,
48 kAccountsPrefShowUserNamesOnSignIn,
49 kAccountsPrefSupervisedUsersEnabled,
50 kAccountsPrefTransferSAMLCookies,
51 kAccountsPrefUsers,
52 kAllowRedeemChromeOsRegistrationOffers,
53 kAllowedConnectionTypesForUpdate,
54 kAppPack,
55 kAttestationForContentProtectionEnabled,
56 kDeviceAttestationEnabled,
57 kDeviceOwner,
58 kIdleLogoutTimeout,
59 kIdleLogoutWarningDuration,
60 kPolicyMissingMitigationMode,
61 kReleaseChannel,
62 kReleaseChannelDelegated,
63 kReportDeviceActivityTimes,
64 kReportDeviceBootMode,
65 kReportDeviceLocation,
66 kReportDeviceNetworkInterfaces,
67 kReportDeviceUsers,
68 kReportDeviceVersionInfo,
69 kScreenSaverExtensionId,
70 kScreenSaverTimeout,
71 kServiceAccountIdentity,
72 kSignedDataRoamingEnabled,
73 kStartUpFlags,
74 kStartUpUrls,
75 kStatsReportingPref,
76 kSystemTimezonePolicy,
77 kSystemUse24HourClock,
78 kUpdateDisabled,
79 kVariationsRestrictParameter,
80 };
81
HasOldMetricsFile()82 bool HasOldMetricsFile() {
83 // TODO(pastarmovj): Remove this once migration is not needed anymore.
84 // If the value is not set we should try to migrate legacy consent file.
85 // Loading consent file state causes us to do blocking IO on UI thread.
86 // Temporarily allow it until we fix http://crbug.com/62626
87 base::ThreadRestrictions::ScopedAllowIO allow_io;
88 return GoogleUpdateSettings::GetCollectStatsConsent();
89 }
90
DecodeLoginPolicies(const em::ChromeDeviceSettingsProto & policy,PrefValueMap * new_values_cache)91 void DecodeLoginPolicies(
92 const em::ChromeDeviceSettingsProto& policy,
93 PrefValueMap* new_values_cache) {
94 // For all our boolean settings the following is applicable:
95 // true is default permissive value and false is safe prohibitive value.
96 // Exceptions:
97 // kAccountsPrefEphemeralUsersEnabled has a default value of false.
98 // kAccountsPrefSupervisedUsersEnabled has a default value of false
99 // for enterprise devices and true for consumer devices.
100 // kAccountsPrefTransferSAMLCookies has a default value of false.
101 if (policy.has_allow_new_users() &&
102 policy.allow_new_users().has_allow_new_users()) {
103 if (policy.allow_new_users().allow_new_users()) {
104 // New users allowed, user whitelist ignored.
105 new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true);
106 } else {
107 // New users not allowed, enforce user whitelist if present.
108 new_values_cache->SetBoolean(kAccountsPrefAllowNewUser,
109 !policy.has_user_whitelist());
110 }
111 } else {
112 // No configured allow-new-users value, enforce whitelist if non-empty.
113 new_values_cache->SetBoolean(
114 kAccountsPrefAllowNewUser,
115 policy.user_whitelist().user_whitelist_size() == 0);
116 }
117
118 new_values_cache->SetBoolean(
119 kAccountsPrefAllowGuest,
120 !policy.has_guest_mode_enabled() ||
121 !policy.guest_mode_enabled().has_guest_mode_enabled() ||
122 policy.guest_mode_enabled().guest_mode_enabled());
123
124 policy::BrowserPolicyConnectorChromeOS* connector =
125 g_browser_process->platform_part()->browser_policy_connector_chromeos();
126 bool supervised_users_enabled = false;
127 if (connector->IsEnterpriseManaged()) {
128 supervised_users_enabled =
129 policy.has_supervised_users_settings() &&
130 policy.supervised_users_settings().has_supervised_users_enabled() &&
131 policy.supervised_users_settings().supervised_users_enabled();
132 } else {
133 supervised_users_enabled =
134 !policy.has_supervised_users_settings() ||
135 !policy.supervised_users_settings().has_supervised_users_enabled() ||
136 policy.supervised_users_settings().supervised_users_enabled();
137 }
138 new_values_cache->SetBoolean(
139 kAccountsPrefSupervisedUsersEnabled, supervised_users_enabled);
140
141 new_values_cache->SetBoolean(
142 kAccountsPrefShowUserNamesOnSignIn,
143 !policy.has_show_user_names() ||
144 !policy.show_user_names().has_show_user_names() ||
145 policy.show_user_names().show_user_names());
146
147 new_values_cache->SetBoolean(
148 kAccountsPrefEphemeralUsersEnabled,
149 policy.has_ephemeral_users_enabled() &&
150 policy.ephemeral_users_enabled().has_ephemeral_users_enabled() &&
151 policy.ephemeral_users_enabled().ephemeral_users_enabled());
152
153 base::ListValue* list = new base::ListValue();
154 const em::UserWhitelistProto& whitelist_proto = policy.user_whitelist();
155 const RepeatedPtrField<std::string>& whitelist =
156 whitelist_proto.user_whitelist();
157 for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
158 it != whitelist.end(); ++it) {
159 list->Append(new base::StringValue(*it));
160 }
161 new_values_cache->SetValue(kAccountsPrefUsers, list);
162
163 scoped_ptr<base::ListValue> account_list(new base::ListValue());
164 const em::DeviceLocalAccountsProto device_local_accounts_proto =
165 policy.device_local_accounts();
166 const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts =
167 device_local_accounts_proto.account();
168 RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry;
169 for (entry = accounts.begin(); entry != accounts.end(); ++entry) {
170 scoped_ptr<base::DictionaryValue> entry_dict(new base::DictionaryValue());
171 if (entry->has_type()) {
172 if (entry->has_account_id()) {
173 entry_dict->SetStringWithoutPathExpansion(
174 kAccountsPrefDeviceLocalAccountsKeyId, entry->account_id());
175 }
176 entry_dict->SetIntegerWithoutPathExpansion(
177 kAccountsPrefDeviceLocalAccountsKeyType, entry->type());
178 if (entry->kiosk_app().has_app_id()) {
179 entry_dict->SetStringWithoutPathExpansion(
180 kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
181 entry->kiosk_app().app_id());
182 }
183 } else if (entry->has_deprecated_public_session_id()) {
184 // Deprecated public session specification.
185 entry_dict->SetStringWithoutPathExpansion(
186 kAccountsPrefDeviceLocalAccountsKeyId,
187 entry->deprecated_public_session_id());
188 entry_dict->SetIntegerWithoutPathExpansion(
189 kAccountsPrefDeviceLocalAccountsKeyType,
190 policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION);
191 }
192 account_list->Append(entry_dict.release());
193 }
194 new_values_cache->SetValue(kAccountsPrefDeviceLocalAccounts,
195 account_list.release());
196
197 if (policy.has_device_local_accounts()) {
198 if (policy.device_local_accounts().has_auto_login_id()) {
199 new_values_cache->SetString(
200 kAccountsPrefDeviceLocalAccountAutoLoginId,
201 policy.device_local_accounts().auto_login_id());
202 }
203 if (policy.device_local_accounts().has_auto_login_delay()) {
204 new_values_cache->SetInteger(
205 kAccountsPrefDeviceLocalAccountAutoLoginDelay,
206 policy.device_local_accounts().auto_login_delay());
207 }
208 }
209
210 new_values_cache->SetBoolean(
211 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled,
212 policy.device_local_accounts().enable_auto_login_bailout());
213 new_values_cache->SetBoolean(
214 kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline,
215 policy.device_local_accounts().prompt_for_network_when_offline());
216
217 if (policy.has_start_up_flags()) {
218 base::ListValue* list = new base::ListValue();
219 const em::StartUpFlagsProto& flags_proto = policy.start_up_flags();
220 const RepeatedPtrField<std::string>& flags = flags_proto.flags();
221 for (RepeatedPtrField<std::string>::const_iterator it = flags.begin();
222 it != flags.end(); ++it) {
223 list->Append(new base::StringValue(*it));
224 }
225 new_values_cache->SetValue(kStartUpFlags, list);
226 }
227
228 if (policy.has_saml_settings()) {
229 new_values_cache->SetBoolean(
230 kAccountsPrefTransferSAMLCookies,
231 policy.saml_settings().transfer_saml_cookies());
232 }
233 }
234
DecodeKioskPolicies(const em::ChromeDeviceSettingsProto & policy,PrefValueMap * new_values_cache)235 void DecodeKioskPolicies(
236 const em::ChromeDeviceSettingsProto& policy,
237 PrefValueMap* new_values_cache) {
238 if (policy.has_forced_logout_timeouts()) {
239 if (policy.forced_logout_timeouts().has_idle_logout_timeout()) {
240 new_values_cache->SetInteger(
241 kIdleLogoutTimeout,
242 policy.forced_logout_timeouts().idle_logout_timeout());
243 }
244
245 if (policy.forced_logout_timeouts().has_idle_logout_warning_duration()) {
246 new_values_cache->SetInteger(
247 kIdleLogoutWarningDuration,
248 policy.forced_logout_timeouts().idle_logout_warning_duration());
249 }
250 }
251
252 if (policy.has_login_screen_saver()) {
253 if (policy.login_screen_saver().has_screen_saver_timeout()) {
254 new_values_cache->SetInteger(
255 kScreenSaverTimeout,
256 policy.login_screen_saver().screen_saver_timeout());
257 }
258
259 if (policy.login_screen_saver().has_screen_saver_extension_id()) {
260 new_values_cache->SetString(
261 kScreenSaverExtensionId,
262 policy.login_screen_saver().screen_saver_extension_id());
263 }
264 }
265
266 if (policy.has_app_pack()) {
267 typedef RepeatedPtrField<em::AppPackEntryProto> proto_type;
268 base::ListValue* list = new base::ListValue;
269 const proto_type& app_pack = policy.app_pack().app_pack();
270 for (proto_type::const_iterator it = app_pack.begin();
271 it != app_pack.end(); ++it) {
272 base::DictionaryValue* entry = new base::DictionaryValue;
273 if (it->has_extension_id()) {
274 entry->SetStringWithoutPathExpansion(kAppPackKeyExtensionId,
275 it->extension_id());
276 }
277 if (it->has_update_url()) {
278 entry->SetStringWithoutPathExpansion(kAppPackKeyUpdateUrl,
279 it->update_url());
280 }
281 list->Append(entry);
282 }
283 new_values_cache->SetValue(kAppPack, list);
284 }
285
286 if (policy.has_start_up_urls()) {
287 base::ListValue* list = new base::ListValue();
288 const em::StartUpUrlsProto& urls_proto = policy.start_up_urls();
289 const RepeatedPtrField<std::string>& urls = urls_proto.start_up_urls();
290 for (RepeatedPtrField<std::string>::const_iterator it = urls.begin();
291 it != urls.end(); ++it) {
292 list->Append(new base::StringValue(*it));
293 }
294 new_values_cache->SetValue(kStartUpUrls, list);
295 }
296 }
297
DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto & policy,PrefValueMap * new_values_cache)298 void DecodeNetworkPolicies(
299 const em::ChromeDeviceSettingsProto& policy,
300 PrefValueMap* new_values_cache) {
301 // kSignedDataRoamingEnabled has a default value of false.
302 new_values_cache->SetBoolean(
303 kSignedDataRoamingEnabled,
304 policy.has_data_roaming_enabled() &&
305 policy.data_roaming_enabled().has_data_roaming_enabled() &&
306 policy.data_roaming_enabled().data_roaming_enabled());
307 }
308
DecodeAutoUpdatePolicies(const em::ChromeDeviceSettingsProto & policy,PrefValueMap * new_values_cache)309 void DecodeAutoUpdatePolicies(
310 const em::ChromeDeviceSettingsProto& policy,
311 PrefValueMap* new_values_cache) {
312 if (policy.has_auto_update_settings()) {
313 const em::AutoUpdateSettingsProto& au_settings_proto =
314 policy.auto_update_settings();
315 if (au_settings_proto.has_update_disabled()) {
316 new_values_cache->SetBoolean(kUpdateDisabled,
317 au_settings_proto.update_disabled());
318 }
319 const RepeatedField<int>& allowed_connection_types =
320 au_settings_proto.allowed_connection_types();
321 base::ListValue* list = new base::ListValue();
322 for (RepeatedField<int>::const_iterator i(allowed_connection_types.begin());
323 i != allowed_connection_types.end(); ++i) {
324 list->Append(new base::FundamentalValue(*i));
325 }
326 new_values_cache->SetValue(kAllowedConnectionTypesForUpdate, list);
327 }
328 }
329
DecodeReportingPolicies(const em::ChromeDeviceSettingsProto & policy,PrefValueMap * new_values_cache)330 void DecodeReportingPolicies(
331 const em::ChromeDeviceSettingsProto& policy,
332 PrefValueMap* new_values_cache) {
333 if (policy.has_device_reporting()) {
334 const em::DeviceReportingProto& reporting_policy =
335 policy.device_reporting();
336 if (reporting_policy.has_report_version_info()) {
337 new_values_cache->SetBoolean(
338 kReportDeviceVersionInfo,
339 reporting_policy.report_version_info());
340 }
341 if (reporting_policy.has_report_activity_times()) {
342 new_values_cache->SetBoolean(
343 kReportDeviceActivityTimes,
344 reporting_policy.report_activity_times());
345 }
346 if (reporting_policy.has_report_boot_mode()) {
347 new_values_cache->SetBoolean(
348 kReportDeviceBootMode,
349 reporting_policy.report_boot_mode());
350 }
351 if (reporting_policy.has_report_network_interfaces()) {
352 new_values_cache->SetBoolean(
353 kReportDeviceNetworkInterfaces,
354 reporting_policy.report_network_interfaces());
355 }
356 if (reporting_policy.has_report_users()) {
357 new_values_cache->SetBoolean(
358 kReportDeviceUsers,
359 reporting_policy.report_users());
360 }
361 }
362 }
363
DecodeGenericPolicies(const em::ChromeDeviceSettingsProto & policy,PrefValueMap * new_values_cache)364 void DecodeGenericPolicies(
365 const em::ChromeDeviceSettingsProto& policy,
366 PrefValueMap* new_values_cache) {
367 if (policy.has_metrics_enabled()) {
368 new_values_cache->SetBoolean(kStatsReportingPref,
369 policy.metrics_enabled().metrics_enabled());
370 } else {
371 new_values_cache->SetBoolean(kStatsReportingPref, HasOldMetricsFile());
372 }
373
374 if (!policy.has_release_channel() ||
375 !policy.release_channel().has_release_channel()) {
376 // Default to an invalid channel (will be ignored).
377 new_values_cache->SetString(kReleaseChannel, "");
378 } else {
379 new_values_cache->SetString(kReleaseChannel,
380 policy.release_channel().release_channel());
381 }
382
383 new_values_cache->SetBoolean(
384 kReleaseChannelDelegated,
385 policy.has_release_channel() &&
386 policy.release_channel().has_release_channel_delegated() &&
387 policy.release_channel().release_channel_delegated());
388
389 if (policy.has_system_timezone()) {
390 if (policy.system_timezone().has_timezone()) {
391 new_values_cache->SetString(
392 kSystemTimezonePolicy,
393 policy.system_timezone().timezone());
394 }
395 }
396
397 if (policy.has_use_24hour_clock()) {
398 if (policy.use_24hour_clock().has_use_24hour_clock()) {
399 new_values_cache->SetBoolean(
400 kSystemUse24HourClock, policy.use_24hour_clock().use_24hour_clock());
401 }
402 }
403
404 if (policy.has_allow_redeem_offers()) {
405 new_values_cache->SetBoolean(
406 kAllowRedeemChromeOsRegistrationOffers,
407 policy.allow_redeem_offers().allow_redeem_offers());
408 } else {
409 new_values_cache->SetBoolean(
410 kAllowRedeemChromeOsRegistrationOffers,
411 true);
412 }
413
414 if (policy.has_variations_parameter()) {
415 new_values_cache->SetString(
416 kVariationsRestrictParameter,
417 policy.variations_parameter().parameter());
418 }
419
420 new_values_cache->SetBoolean(
421 kDeviceAttestationEnabled,
422 policy.attestation_settings().attestation_enabled());
423
424 if (policy.has_attestation_settings() &&
425 policy.attestation_settings().has_content_protection_enabled()) {
426 new_values_cache->SetBoolean(
427 kAttestationForContentProtectionEnabled,
428 policy.attestation_settings().content_protection_enabled());
429 } else {
430 new_values_cache->SetBoolean(kAttestationForContentProtectionEnabled, true);
431 }
432 }
433
434 } // namespace
435
DeviceSettingsProvider(const NotifyObserversCallback & notify_cb,DeviceSettingsService * device_settings_service)436 DeviceSettingsProvider::DeviceSettingsProvider(
437 const NotifyObserversCallback& notify_cb,
438 DeviceSettingsService* device_settings_service)
439 : CrosSettingsProvider(notify_cb),
440 device_settings_service_(device_settings_service),
441 trusted_status_(TEMPORARILY_UNTRUSTED),
442 ownership_status_(device_settings_service_->GetOwnershipStatus()),
443 store_callback_factory_(this) {
444 device_settings_service_->AddObserver(this);
445 if (!UpdateFromService()) {
446 // Make sure we have at least the cache data immediately.
447 RetrieveCachedData();
448 }
449 }
450
~DeviceSettingsProvider()451 DeviceSettingsProvider::~DeviceSettingsProvider() {
452 device_settings_service_->RemoveObserver(this);
453 }
454
455 // static
IsDeviceSetting(const std::string & name)456 bool DeviceSettingsProvider::IsDeviceSetting(const std::string& name) {
457 const char** end = kKnownSettings + arraysize(kKnownSettings);
458 return std::find(kKnownSettings, end, name) != end;
459 }
460
DoSet(const std::string & path,const base::Value & in_value)461 void DeviceSettingsProvider::DoSet(const std::string& path,
462 const base::Value& in_value) {
463 // Make sure that either the current user is the device owner or the
464 // device doesn't have an owner yet.
465 if (!(device_settings_service_->HasPrivateOwnerKey() ||
466 ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)) {
467 LOG(WARNING) << "Changing settings from non-owner, setting=" << path;
468
469 // Revert UI change.
470 NotifyObservers(path);
471 return;
472 }
473
474 if (IsDeviceSetting(path)) {
475 pending_changes_.push_back(PendingQueueElement(path, in_value.DeepCopy()));
476 if (!store_callback_factory_.HasWeakPtrs())
477 SetInPolicy();
478 } else {
479 NOTREACHED() << "Try to set unhandled cros setting " << path;
480 }
481 }
482
OwnershipStatusChanged()483 void DeviceSettingsProvider::OwnershipStatusChanged() {
484 DeviceSettingsService::OwnershipStatus new_ownership_status =
485 device_settings_service_->GetOwnershipStatus();
486
487 // If the device just became owned, write the settings accumulated in the
488 // cache to device settings proper. It is important that writing only happens
489 // in this case, as during normal operation, the contents of the cache should
490 // never overwrite actual device settings.
491 if (new_ownership_status == DeviceSettingsService::OWNERSHIP_TAKEN &&
492 ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE &&
493 device_settings_service_->HasPrivateOwnerKey()) {
494 // There shouldn't be any pending writes, since the cache writes are all
495 // immediate.
496 DCHECK(!store_callback_factory_.HasWeakPtrs());
497
498 trusted_status_ = TEMPORARILY_UNTRUSTED;
499 // Apply the locally-accumulated device settings on top of the initial
500 // settings from the service and write back the result.
501 if (device_settings_service_->device_settings()) {
502 em::ChromeDeviceSettingsProto new_settings(
503 *device_settings_service_->device_settings());
504 new_settings.MergeFrom(device_settings_);
505 device_settings_.Swap(&new_settings);
506 }
507 StoreDeviceSettings();
508 }
509
510 // The owner key might have become available, allowing migration to happen.
511 AttemptMigration();
512
513 ownership_status_ = new_ownership_status;
514 }
515
DeviceSettingsUpdated()516 void DeviceSettingsProvider::DeviceSettingsUpdated() {
517 if (!store_callback_factory_.HasWeakPtrs())
518 UpdateAndProceedStoring();
519 }
520
RetrieveCachedData()521 void DeviceSettingsProvider::RetrieveCachedData() {
522 em::PolicyData policy_data;
523 if (!device_settings_cache::Retrieve(&policy_data,
524 g_browser_process->local_state()) ||
525 !device_settings_.ParseFromString(policy_data.policy_value())) {
526 VLOG(1) << "Can't retrieve temp store, possibly not created yet.";
527 }
528
529 UpdateValuesCache(policy_data, device_settings_, trusted_status_);
530 }
531
SetInPolicy()532 void DeviceSettingsProvider::SetInPolicy() {
533 if (pending_changes_.empty()) {
534 NOTREACHED();
535 return;
536 }
537
538 if (RequestTrustedEntity() != TRUSTED) {
539 // Re-sync device settings before proceeding.
540 device_settings_service_->Load();
541 return;
542 }
543
544 std::string prop(pending_changes_.front().first);
545 scoped_ptr<base::Value> value(pending_changes_.front().second);
546 pending_changes_.pop_front();
547
548 trusted_status_ = TEMPORARILY_UNTRUSTED;
549 if (prop == kAccountsPrefAllowNewUser) {
550 em::AllowNewUsersProto* allow =
551 device_settings_.mutable_allow_new_users();
552 bool allow_value;
553 if (value->GetAsBoolean(&allow_value))
554 allow->set_allow_new_users(allow_value);
555 else
556 NOTREACHED();
557 } else if (prop == kAccountsPrefAllowGuest) {
558 em::GuestModeEnabledProto* guest =
559 device_settings_.mutable_guest_mode_enabled();
560 bool guest_value;
561 if (value->GetAsBoolean(&guest_value))
562 guest->set_guest_mode_enabled(guest_value);
563 else
564 NOTREACHED();
565 } else if (prop == kAccountsPrefSupervisedUsersEnabled) {
566 em::SupervisedUsersSettingsProto* supervised =
567 device_settings_.mutable_supervised_users_settings();
568 bool supervised_value;
569 if (value->GetAsBoolean(&supervised_value))
570 supervised->set_supervised_users_enabled(supervised_value);
571 else
572 NOTREACHED();
573 } else if (prop == kAccountsPrefShowUserNamesOnSignIn) {
574 em::ShowUserNamesOnSigninProto* show =
575 device_settings_.mutable_show_user_names();
576 bool show_value;
577 if (value->GetAsBoolean(&show_value))
578 show->set_show_user_names(show_value);
579 else
580 NOTREACHED();
581 } else if (prop == kAccountsPrefDeviceLocalAccounts) {
582 em::DeviceLocalAccountsProto* device_local_accounts =
583 device_settings_.mutable_device_local_accounts();
584 device_local_accounts->clear_account();
585 const base::ListValue* accounts_list = NULL;
586 if (value->GetAsList(&accounts_list)) {
587 for (base::ListValue::const_iterator entry(accounts_list->begin());
588 entry != accounts_list->end(); ++entry) {
589 const base::DictionaryValue* entry_dict = NULL;
590 if ((*entry)->GetAsDictionary(&entry_dict)) {
591 em::DeviceLocalAccountInfoProto* account =
592 device_local_accounts->add_account();
593 std::string account_id;
594 if (entry_dict->GetStringWithoutPathExpansion(
595 kAccountsPrefDeviceLocalAccountsKeyId, &account_id)) {
596 account->set_account_id(account_id);
597 }
598 int type;
599 if (entry_dict->GetIntegerWithoutPathExpansion(
600 kAccountsPrefDeviceLocalAccountsKeyType, &type)) {
601 account->set_type(
602 static_cast<em::DeviceLocalAccountInfoProto::AccountType>(
603 type));
604 }
605 std::string kiosk_app_id;
606 if (entry_dict->GetStringWithoutPathExpansion(
607 kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
608 &kiosk_app_id)) {
609 account->mutable_kiosk_app()->set_app_id(kiosk_app_id);
610 }
611 } else {
612 NOTREACHED();
613 }
614 }
615 } else {
616 NOTREACHED();
617 }
618 } else if (prop == kAccountsPrefDeviceLocalAccountAutoLoginId) {
619 em::DeviceLocalAccountsProto* device_local_accounts =
620 device_settings_.mutable_device_local_accounts();
621 std::string id;
622 if (value->GetAsString(&id))
623 device_local_accounts->set_auto_login_id(id);
624 else
625 NOTREACHED();
626 } else if (prop == kAccountsPrefDeviceLocalAccountAutoLoginDelay) {
627 em::DeviceLocalAccountsProto* device_local_accounts =
628 device_settings_.mutable_device_local_accounts();
629 int delay;
630 if (value->GetAsInteger(&delay))
631 device_local_accounts->set_auto_login_delay(delay);
632 else
633 NOTREACHED();
634 } else if (prop == kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled) {
635 em::DeviceLocalAccountsProto* device_local_accounts =
636 device_settings_.mutable_device_local_accounts();
637 bool enabled;
638 if (value->GetAsBoolean(&enabled))
639 device_local_accounts->set_enable_auto_login_bailout(enabled);
640 else
641 NOTREACHED();
642 } else if (prop ==
643 kAccountsPrefDeviceLocalAccountPromptForNetworkWhenOffline) {
644 em::DeviceLocalAccountsProto* device_local_accounts =
645 device_settings_.mutable_device_local_accounts();
646 bool should_prompt;
647 if (value->GetAsBoolean(&should_prompt))
648 device_local_accounts->set_prompt_for_network_when_offline(should_prompt);
649 else
650 NOTREACHED();
651 } else if (prop == kSignedDataRoamingEnabled) {
652 em::DataRoamingEnabledProto* roam =
653 device_settings_.mutable_data_roaming_enabled();
654 bool roaming_value = false;
655 if (value->GetAsBoolean(&roaming_value))
656 roam->set_data_roaming_enabled(roaming_value);
657 else
658 NOTREACHED();
659 } else if (prop == kReleaseChannel) {
660 em::ReleaseChannelProto* release_channel =
661 device_settings_.mutable_release_channel();
662 std::string channel_value;
663 if (value->GetAsString(&channel_value))
664 release_channel->set_release_channel(channel_value);
665 else
666 NOTREACHED();
667 } else if (prop == kStatsReportingPref) {
668 em::MetricsEnabledProto* metrics =
669 device_settings_.mutable_metrics_enabled();
670 bool metrics_value = false;
671 if (value->GetAsBoolean(&metrics_value))
672 metrics->set_metrics_enabled(metrics_value);
673 else
674 NOTREACHED();
675 ApplyMetricsSetting(false, metrics_value);
676 } else if (prop == kAccountsPrefUsers) {
677 em::UserWhitelistProto* whitelist_proto =
678 device_settings_.mutable_user_whitelist();
679 whitelist_proto->clear_user_whitelist();
680 const base::ListValue* users;
681 if (value->GetAsList(&users)) {
682 for (base::ListValue::const_iterator i = users->begin();
683 i != users->end(); ++i) {
684 std::string email;
685 if ((*i)->GetAsString(&email))
686 whitelist_proto->add_user_whitelist(email);
687 }
688 }
689 } else if (prop == kAccountsPrefEphemeralUsersEnabled) {
690 em::EphemeralUsersEnabledProto* ephemeral_users_enabled =
691 device_settings_.mutable_ephemeral_users_enabled();
692 bool ephemeral_users_enabled_value = false;
693 if (value->GetAsBoolean(&ephemeral_users_enabled_value)) {
694 ephemeral_users_enabled->set_ephemeral_users_enabled(
695 ephemeral_users_enabled_value);
696 } else {
697 NOTREACHED();
698 }
699 } else if (prop == kAllowRedeemChromeOsRegistrationOffers) {
700 em::AllowRedeemChromeOsRegistrationOffersProto* allow_redeem_offers =
701 device_settings_.mutable_allow_redeem_offers();
702 bool allow_redeem_offers_value;
703 if (value->GetAsBoolean(&allow_redeem_offers_value)) {
704 allow_redeem_offers->set_allow_redeem_offers(
705 allow_redeem_offers_value);
706 } else {
707 NOTREACHED();
708 }
709 } else if (prop == kStartUpFlags) {
710 em::StartUpFlagsProto* flags_proto =
711 device_settings_.mutable_start_up_flags();
712 flags_proto->Clear();
713 const base::ListValue* flags;
714 if (value->GetAsList(&flags)) {
715 for (base::ListValue::const_iterator i = flags->begin();
716 i != flags->end(); ++i) {
717 std::string flag;
718 if ((*i)->GetAsString(&flag))
719 flags_proto->add_flags(flag);
720 }
721 }
722 } else if (prop == kSystemUse24HourClock) {
723 em::SystemUse24HourClockProto* use_24hour_clock_proto =
724 device_settings_.mutable_use_24hour_clock();
725 use_24hour_clock_proto->Clear();
726 bool use_24hour_clock_value;
727 if (value->GetAsBoolean(&use_24hour_clock_value)) {
728 use_24hour_clock_proto->set_use_24hour_clock(use_24hour_clock_value);
729 } else {
730 NOTREACHED();
731 }
732 } else if (prop == kAttestationForContentProtectionEnabled) {
733 em::AttestationSettingsProto* attestation_settings =
734 device_settings_.mutable_attestation_settings();
735 bool setting_enabled;
736 if (value->GetAsBoolean(&setting_enabled)) {
737 attestation_settings->set_content_protection_enabled(setting_enabled);
738 } else {
739 NOTREACHED();
740 }
741 } else {
742 // The remaining settings don't support Set(), since they are not
743 // intended to be customizable by the user:
744 // kAccountsPrefTransferSAMLCookies
745 // kAppPack
746 // kDeviceAttestationEnabled
747 // kDeviceOwner
748 // kIdleLogoutTimeout
749 // kIdleLogoutWarningDuration
750 // kReleaseChannelDelegated
751 // kReportDeviceActivityTimes
752 // kReportDeviceBootMode
753 // kReportDeviceLocation
754 // kReportDeviceVersionInfo
755 // kReportDeviceNetworkInterfaces
756 // kReportDeviceUsers
757 // kScreenSaverExtensionId
758 // kScreenSaverTimeout
759 // kServiceAccountIdentity
760 // kStartUpUrls
761 // kSystemTimezonePolicy
762 // kVariationsRestrictParameter
763
764 LOG(FATAL) << "Device setting " << prop << " is read-only.";
765 }
766
767 em::PolicyData data;
768 data.set_username(device_settings_service_->GetUsername());
769 CHECK(device_settings_.SerializeToString(data.mutable_policy_value()));
770
771 // Set the cache to the updated value.
772 UpdateValuesCache(data, device_settings_, trusted_status_);
773
774 if (ownership_status_ == DeviceSettingsService::OWNERSHIP_TAKEN) {
775 StoreDeviceSettings();
776 } else {
777 if (!device_settings_cache::Store(data, g_browser_process->local_state()))
778 LOG(ERROR) << "Couldn't store to the temp storage.";
779
780 // OnStorePolicyCompleted won't get called in this case so proceed with any
781 // pending operations immediately.
782 if (!pending_changes_.empty())
783 SetInPolicy();
784 }
785 }
786
UpdateValuesCache(const em::PolicyData & policy_data,const em::ChromeDeviceSettingsProto & settings,TrustedStatus trusted_status)787 void DeviceSettingsProvider::UpdateValuesCache(
788 const em::PolicyData& policy_data,
789 const em::ChromeDeviceSettingsProto& settings,
790 TrustedStatus trusted_status) {
791 PrefValueMap new_values_cache;
792
793 if (policy_data.has_username() && !policy_data.has_request_token())
794 new_values_cache.SetString(kDeviceOwner, policy_data.username());
795
796 if (policy_data.has_service_account_identity()) {
797 new_values_cache.SetString(kServiceAccountIdentity,
798 policy_data.service_account_identity());
799 }
800
801 DecodeLoginPolicies(settings, &new_values_cache);
802 DecodeKioskPolicies(settings, &new_values_cache);
803 DecodeNetworkPolicies(settings, &new_values_cache);
804 DecodeAutoUpdatePolicies(settings, &new_values_cache);
805 DecodeReportingPolicies(settings, &new_values_cache);
806 DecodeGenericPolicies(settings, &new_values_cache);
807
808 // Collect all notifications but send them only after we have swapped the
809 // cache so that if somebody actually reads the cache will be already valid.
810 std::vector<std::string> notifications;
811 // Go through the new values and verify in the old ones.
812 PrefValueMap::iterator iter = new_values_cache.begin();
813 for (; iter != new_values_cache.end(); ++iter) {
814 const base::Value* old_value;
815 if (!values_cache_.GetValue(iter->first, &old_value) ||
816 !old_value->Equals(iter->second)) {
817 notifications.push_back(iter->first);
818 }
819 }
820 // Now check for values that have been removed from the policy blob.
821 for (iter = values_cache_.begin(); iter != values_cache_.end(); ++iter) {
822 const base::Value* value;
823 if (!new_values_cache.GetValue(iter->first, &value))
824 notifications.push_back(iter->first);
825 }
826 // Swap and notify.
827 values_cache_.Swap(&new_values_cache);
828 trusted_status_ = trusted_status;
829 for (size_t i = 0; i < notifications.size(); ++i)
830 NotifyObservers(notifications[i]);
831 }
832
ApplyMetricsSetting(bool use_file,bool new_value)833 void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file,
834 bool new_value) {
835 // TODO(pastarmovj): Remove this once migration is not needed anymore.
836 // If the value is not set we should try to migrate legacy consent file.
837 if (use_file) {
838 new_value = HasOldMetricsFile();
839 // Make sure the values will get eventually written to the policy file.
840 migration_values_.SetBoolean(kStatsReportingPref, new_value);
841 AttemptMigration();
842 VLOG(1) << "No metrics policy set will revert to checking "
843 << "consent file which is "
844 << (new_value ? "on." : "off.");
845 UMA_HISTOGRAM_COUNTS("DeviceSettings.MetricsMigrated", 1);
846 }
847 VLOG(1) << "Metrics policy is being set to : " << new_value
848 << "(use file : " << use_file << ")";
849 // TODO(pastarmovj): Remove this once we don't need to regenerate the
850 // consent file for the GUID anymore.
851 InitiateMetricsReportingChange(new_value, OnMetricsReportingCallbackType());
852 }
853
ApplySideEffects(const em::ChromeDeviceSettingsProto & settings)854 void DeviceSettingsProvider::ApplySideEffects(
855 const em::ChromeDeviceSettingsProto& settings) {
856 // First migrate metrics settings as needed.
857 if (settings.has_metrics_enabled())
858 ApplyMetricsSetting(false, settings.metrics_enabled().metrics_enabled());
859 else
860 ApplyMetricsSetting(true, false);
861 }
862
MitigateMissingPolicy()863 bool DeviceSettingsProvider::MitigateMissingPolicy() {
864 // First check if the device has been owned already and if not exit
865 // immediately.
866 policy::BrowserPolicyConnectorChromeOS* connector =
867 g_browser_process->platform_part()->browser_policy_connector_chromeos();
868 if (connector->GetDeviceMode() != policy::DEVICE_MODE_CONSUMER)
869 return false;
870
871 // If we are here the policy file were corrupted or missing. This can happen
872 // because we are migrating Pre R11 device to the new secure policies or there
873 // was an attempt to circumvent policy system. In this case we should populate
874 // the policy cache with "safe-mode" defaults which should allow the owner to
875 // log in but lock the device for anyone else until the policy blob has been
876 // recreated by the session manager.
877 LOG(ERROR) << "Corruption of the policy data has been detected."
878 << "Switching to \"safe-mode\" policies until the owner logs in "
879 << "to regenerate the policy data.";
880
881 device_settings_.Clear();
882 device_settings_.mutable_allow_new_users()->set_allow_new_users(true);
883 device_settings_.mutable_guest_mode_enabled()->set_guest_mode_enabled(true);
884 em::PolicyData empty_policy_data;
885 UpdateValuesCache(empty_policy_data, device_settings_, TRUSTED);
886 values_cache_.SetBoolean(kPolicyMissingMitigationMode, true);
887
888 return true;
889 }
890
Get(const std::string & path) const891 const base::Value* DeviceSettingsProvider::Get(const std::string& path) const {
892 if (IsDeviceSetting(path)) {
893 const base::Value* value;
894 if (values_cache_.GetValue(path, &value))
895 return value;
896 } else {
897 NOTREACHED() << "Trying to get non cros setting.";
898 }
899
900 return NULL;
901 }
902
903 DeviceSettingsProvider::TrustedStatus
PrepareTrustedValues(const base::Closure & cb)904 DeviceSettingsProvider::PrepareTrustedValues(const base::Closure& cb) {
905 TrustedStatus status = RequestTrustedEntity();
906 if (status == TEMPORARILY_UNTRUSTED && !cb.is_null())
907 callbacks_.push_back(cb);
908 return status;
909 }
910
HandlesSetting(const std::string & path) const911 bool DeviceSettingsProvider::HandlesSetting(const std::string& path) const {
912 return IsDeviceSetting(path);
913 }
914
915 DeviceSettingsProvider::TrustedStatus
RequestTrustedEntity()916 DeviceSettingsProvider::RequestTrustedEntity() {
917 if (ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)
918 return TRUSTED;
919 return trusted_status_;
920 }
921
UpdateAndProceedStoring()922 void DeviceSettingsProvider::UpdateAndProceedStoring() {
923 // Re-sync the cache from the service.
924 UpdateFromService();
925
926 // Trigger the next change if necessary.
927 if (trusted_status_ == TRUSTED && !pending_changes_.empty())
928 SetInPolicy();
929 }
930
UpdateFromService()931 bool DeviceSettingsProvider::UpdateFromService() {
932 bool settings_loaded = false;
933 switch (device_settings_service_->status()) {
934 case DeviceSettingsService::STORE_SUCCESS: {
935 const em::PolicyData* policy_data =
936 device_settings_service_->policy_data();
937 const em::ChromeDeviceSettingsProto* device_settings =
938 device_settings_service_->device_settings();
939 if (policy_data && device_settings) {
940 if (!device_settings_cache::Store(*policy_data,
941 g_browser_process->local_state())) {
942 LOG(ERROR) << "Couldn't update the local state cache.";
943 }
944 UpdateValuesCache(*policy_data, *device_settings, TRUSTED);
945 device_settings_ = *device_settings;
946
947 // TODO(pastarmovj): Make those side effects responsibility of the
948 // respective subsystems.
949 ApplySideEffects(*device_settings);
950
951 settings_loaded = true;
952 } else {
953 // Initial policy load is still pending.
954 trusted_status_ = TEMPORARILY_UNTRUSTED;
955 }
956 break;
957 }
958 case DeviceSettingsService::STORE_NO_POLICY:
959 if (MitigateMissingPolicy())
960 break;
961 // fall through.
962 case DeviceSettingsService::STORE_KEY_UNAVAILABLE:
963 VLOG(1) << "No policies present yet, will use the temp storage.";
964 trusted_status_ = PERMANENTLY_UNTRUSTED;
965 break;
966 case DeviceSettingsService::STORE_POLICY_ERROR:
967 case DeviceSettingsService::STORE_VALIDATION_ERROR:
968 case DeviceSettingsService::STORE_INVALID_POLICY:
969 case DeviceSettingsService::STORE_OPERATION_FAILED:
970 LOG(ERROR) << "Failed to retrieve cros policies. Reason: "
971 << device_settings_service_->status();
972 trusted_status_ = PERMANENTLY_UNTRUSTED;
973 break;
974 case DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
975 // The policy has failed to validate due to temporary error but it might
976 // take a long time until we recover so behave as it is a permanent error.
977 LOG(ERROR) << "Failed to retrieve cros policies because a temporary "
978 << "validation error has occurred. Retrying might succeed.";
979 trusted_status_ = PERMANENTLY_UNTRUSTED;
980 break;
981 }
982
983 // Notify the observers we are done.
984 std::vector<base::Closure> callbacks;
985 callbacks.swap(callbacks_);
986 for (size_t i = 0; i < callbacks.size(); ++i)
987 callbacks[i].Run();
988
989 return settings_loaded;
990 }
991
StoreDeviceSettings()992 void DeviceSettingsProvider::StoreDeviceSettings() {
993 // Mute all previous callbacks to guarantee the |pending_changes_| queue is
994 // processed serially.
995 store_callback_factory_.InvalidateWeakPtrs();
996
997 device_settings_service_->SignAndStore(
998 scoped_ptr<em::ChromeDeviceSettingsProto>(
999 new em::ChromeDeviceSettingsProto(device_settings_)),
1000 base::Bind(&DeviceSettingsProvider::UpdateAndProceedStoring,
1001 store_callback_factory_.GetWeakPtr()));
1002 }
1003
AttemptMigration()1004 void DeviceSettingsProvider::AttemptMigration() {
1005 if (device_settings_service_->HasPrivateOwnerKey()) {
1006 PrefValueMap::const_iterator i;
1007 for (i = migration_values_.begin(); i != migration_values_.end(); ++i)
1008 DoSet(i->first, *i->second);
1009 migration_values_.Clear();
1010 }
1011 }
1012
1013 } // namespace chromeos
1014