• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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