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