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