Home | History | Annotate | Download | only in settings
      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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    451 DeviceSettingsProvider::~DeviceSettingsProvider() {
    452   device_settings_service_->RemoveObserver(this);
    453 }
    454 
    455 // static
    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 
    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 
    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 
    516 void DeviceSettingsProvider::DeviceSettingsUpdated() {
    517   if (!store_callback_factory_.HasWeakPtrs())
    518     UpdateAndProceedStoring();
    519 }
    520 
    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 
    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 
    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 
    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 
    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 
    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 
    891 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
    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 
    911 bool DeviceSettingsProvider::HandlesSetting(const std::string& path) const {
    912   return IsDeviceSetting(path);
    913 }
    914 
    915 DeviceSettingsProvider::TrustedStatus
    916     DeviceSettingsProvider::RequestTrustedEntity() {
    917   if (ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)
    918     return TRUSTED;
    919   return trusted_status_;
    920 }
    921 
    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 
    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 
    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 
   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