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