blob: e64750057493e54d2fa8984b2e5b92eaea9a7ced [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/device_settings_provider.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/string_util.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/cros_settings.h"
#include "chrome/browser/chromeos/cros_settings_names.h"
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/signed_settings_cache.h"
#include "chrome/browser/chromeos/login/signed_settings_helper.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/policy/app_pack_updater.h"
#include "chrome/browser/ui/options/options_util.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/installer/util/google_update_settings.h"
#include "content/public/browser/notification_service.h"
using google::protobuf::RepeatedPtrField;
namespace em = enterprise_management;
namespace chromeos {
namespace {
// List of settings handled by the DeviceSettingsProvider.
const char* kKnownSettings[] = {
kAccountsPrefAllowGuest,
kAccountsPrefAllowNewUser,
kAccountsPrefEphemeralUsersEnabled,
kAccountsPrefShowUserNamesOnSignIn,
kAccountsPrefUsers,
kAppPack,
kDeviceOwner,
kIdleLogoutTimeout,
kIdleLogoutWarningDuration,
kReleaseChannel,
kReportDeviceActivityTimes,
kReportDeviceBootMode,
kReportDeviceVersionInfo,
kScreenSaverExtensionId,
kScreenSaverTimeout,
kSettingProxyEverywhere,
kSignedDataRoamingEnabled,
kStatsReportingPref,
};
// Upper bound for number of retries to fetch a signed setting.
static const int kNumRetriesLimit = 9;
// Legacy policy file location. Used to detect migration from pre v12 ChromeOS.
const char kLegacyPolicyFile[] = "/var/lib/whitelist/preferences";
bool IsControlledSetting(const std::string& pref_path) {
const char** end = kKnownSettings + arraysize(kKnownSettings);
return std::find(kKnownSettings, end, pref_path) != end;
}
bool HasOldMetricsFile() {
// TODO(pastarmovj): Remove this once migration is not needed anymore.
// If the value is not set we should try to migrate legacy consent file.
// Loading consent file state causes us to do blocking IO on UI thread.
// Temporarily allow it until we fix http://crbug.com/62626
base::ThreadRestrictions::ScopedAllowIO allow_io;
return GoogleUpdateSettings::GetCollectStatsConsent();
}
} // namespace
DeviceSettingsProvider::DeviceSettingsProvider(
const NotifyObserversCallback& notify_cb)
: CrosSettingsProvider(notify_cb),
ownership_status_(OwnershipService::GetSharedInstance()->GetStatus(true)),
migration_helper_(new SignedSettingsMigrationHelper()),
retries_left_(kNumRetriesLimit),
trusted_(false) {
// Register for notification when ownership is taken so that we can update
// the |ownership_status_| and reload if needed.
registrar_.Add(this, chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
content::NotificationService::AllSources());
// Make sure we have at least the cache data immediately.
RetrieveCachedData();
// Start prefetching preferences.
Reload();
}
DeviceSettingsProvider::~DeviceSettingsProvider() {
}
void DeviceSettingsProvider::Reload() {
// While fetching we can't trust the cache anymore.
trusted_ = false;
if (ownership_status_ == OwnershipService::OWNERSHIP_NONE) {
RetrieveCachedData();
} else {
// Retrieve the real data.
SignedSettingsHelper::Get()->StartRetrievePolicyOp(
base::Bind(&DeviceSettingsProvider::OnRetrievePolicyCompleted,
base::Unretained(this)));
}
}
void DeviceSettingsProvider::DoSet(const std::string& path,
const base::Value& in_value) {
if (!UserManager::Get()->IsCurrentUserOwner() &&
ownership_status_ != OwnershipService::OWNERSHIP_NONE) {
LOG(WARNING) << "Changing settings from non-owner, setting=" << path;
// Revert UI change.
NotifyObservers(path);
return;
}
if (IsControlledSetting(path)) {
pending_changes_.push_back(PendingQueueElement(path, in_value.DeepCopy()));
if (pending_changes_.size() == 1)
SetInPolicy();
} else {
NOTREACHED() << "Try to set unhandled cros setting " << path;
}
}
void DeviceSettingsProvider::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
if (type == chrome::NOTIFICATION_OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
// Reload the policy blob once the owner key has been loaded or updated.
ownership_status_ = OwnershipService::OWNERSHIP_TAKEN;
Reload();
}
}
const em::PolicyData DeviceSettingsProvider::policy() const {
return policy_;
}
void DeviceSettingsProvider::RetrieveCachedData() {
// If there is no owner yet, this function will pull the policy cache from the
// temp storage and use that instead.
em::PolicyData policy;
if (!signed_settings_cache::Retrieve(&policy,
g_browser_process->local_state())) {
VLOG(1) << "Can't retrieve temp store possibly not created yet.";
// Prepare empty data for the case we don't have temp cache yet.
policy.set_policy_type(kDevicePolicyType);
em::ChromeDeviceSettingsProto pol;
policy.set_policy_value(pol.SerializeAsString());
}
policy_ = policy;
UpdateValuesCache();
}
void DeviceSettingsProvider::SetInPolicy() {
if (pending_changes_.empty()) {
NOTREACHED();
return;
}
const std::string& prop = pending_changes_[0].first;
base::Value* value = pending_changes_[0].second;
if (prop == kDeviceOwner) {
// Just store it in the memory cache without trusted checks or persisting.
std::string owner;
if (value->GetAsString(&owner)) {
policy_.set_username(owner);
// In this case the |value_cache_| takes the ownership of |value|.
values_cache_.SetValue(prop, value);
NotifyObservers(prop);
// We can't trust this value anymore until we reload the real username.
trusted_ = false;
pending_changes_.erase(pending_changes_.begin());
if (!pending_changes_.empty())
SetInPolicy();
} else {
NOTREACHED();
}
return;
}
if (!RequestTrustedEntity()) {
// Otherwise we should first reload and apply on top of that.
SignedSettingsHelper::Get()->StartRetrievePolicyOp(
base::Bind(&DeviceSettingsProvider::FinishSetInPolicy,
base::Unretained(this)));
return;
}
trusted_ = false;
em::PolicyData data = policy();
em::ChromeDeviceSettingsProto pol;
pol.ParseFromString(data.policy_value());
if (prop == kAccountsPrefAllowNewUser) {
em::AllowNewUsersProto* allow = pol.mutable_allow_new_users();
bool allow_value;
if (value->GetAsBoolean(&allow_value))
allow->set_allow_new_users(allow_value);
else
NOTREACHED();
} else if (prop == kAccountsPrefAllowGuest) {
em::GuestModeEnabledProto* guest = pol.mutable_guest_mode_enabled();
bool guest_value;
if (value->GetAsBoolean(&guest_value))
guest->set_guest_mode_enabled(guest_value);
else
NOTREACHED();
} else if (prop == kAccountsPrefShowUserNamesOnSignIn) {
em::ShowUserNamesOnSigninProto* show = pol.mutable_show_user_names();
bool show_value;
if (value->GetAsBoolean(&show_value))
show->set_show_user_names(show_value);
else
NOTREACHED();
} else if (prop == kSignedDataRoamingEnabled) {
em::DataRoamingEnabledProto* roam = pol.mutable_data_roaming_enabled();
bool roaming_value = false;
if (value->GetAsBoolean(&roaming_value))
roam->set_data_roaming_enabled(roaming_value);
else
NOTREACHED();
ApplyRoamingSetting(roaming_value);
} else if (prop == kSettingProxyEverywhere) {
// TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed.
std::string proxy_value;
if (value->GetAsString(&proxy_value)) {
bool success =
pol.mutable_device_proxy_settings()->ParseFromString(proxy_value);
DCHECK(success);
} else {
NOTREACHED();
}
} else if (prop == kReleaseChannel) {
em::ReleaseChannelProto* release_channel = pol.mutable_release_channel();
std::string channel_value;
if (value->GetAsString(&channel_value))
release_channel->set_release_channel(channel_value);
else
NOTREACHED();
} else if (prop == kStatsReportingPref) {
em::MetricsEnabledProto* metrics = pol.mutable_metrics_enabled();
bool metrics_value = false;
if (value->GetAsBoolean(&metrics_value))
metrics->set_metrics_enabled(metrics_value);
else
NOTREACHED();
ApplyMetricsSetting(false, metrics_value);
} else if (prop == kAccountsPrefUsers) {
em::UserWhitelistProto* whitelist_proto = pol.mutable_user_whitelist();
whitelist_proto->clear_user_whitelist();
base::ListValue& users = static_cast<base::ListValue&>(*value);
for (base::ListValue::const_iterator i = users.begin();
i != users.end(); ++i) {
std::string email;
if ((*i)->GetAsString(&email))
whitelist_proto->add_user_whitelist(email.c_str());
}
} else if (prop == kAccountsPrefEphemeralUsersEnabled) {
em::EphemeralUsersEnabledProto* ephemeral_users_enabled =
pol.mutable_ephemeral_users_enabled();
bool ephemeral_users_enabled_value = false;
if (value->GetAsBoolean(&ephemeral_users_enabled_value))
ephemeral_users_enabled->set_ephemeral_users_enabled(
ephemeral_users_enabled_value);
else
NOTREACHED();
} else {
// The remaining settings don't support Set(), since they are not
// intended to be customizable by the user:
// kAppPack
// kIdleLogoutTimeout,
// kIdleLogoutWarningDuration,
// kReportDeviceVersionInfo
// kReportDeviceActivityTimes
// kReportDeviceBootMode
// kScreenSaverExtensionId,
// kScreenSaverTimeout,
NOTREACHED();
}
data.set_policy_value(pol.SerializeAsString());
// Set the cache to the updated value.
policy_ = data;
UpdateValuesCache();
if (!signed_settings_cache::Store(data, g_browser_process->local_state()))
LOG(ERROR) << "Couldn't store to the temp storage.";
if (ownership_status_ == OwnershipService::OWNERSHIP_TAKEN) {
em::PolicyFetchResponse policy_envelope;
policy_envelope.set_policy_data(policy_.SerializeAsString());
SignedSettingsHelper::Get()->StartStorePolicyOp(
policy_envelope,
base::Bind(&DeviceSettingsProvider::OnStorePolicyCompleted,
base::Unretained(this)));
} else {
// OnStorePolicyCompleted won't get called in this case so proceed with any
// pending operations immediately.
delete pending_changes_[0].second;
pending_changes_.erase(pending_changes_.begin());
if (!pending_changes_.empty())
SetInPolicy();
}
}
void DeviceSettingsProvider::FinishSetInPolicy(
SignedSettings::ReturnCode code,
const em::PolicyFetchResponse& policy) {
if (code != SignedSettings::SUCCESS) {
LOG(ERROR) << "Can't serialize to policy error code: " << code;
Reload();
return;
}
// Update the internal caches and set the trusted flag to true so that we
// can pass the trustedness check in the second call to SetInPolicy.
OnRetrievePolicyCompleted(code, policy);
SetInPolicy();
}
void DeviceSettingsProvider::DecodeLoginPolicies(
const em::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const {
// For all our boolean settings the following is applicable:
// true is default permissive value and false is safe prohibitive value.
// Exceptions:
// kSignedDataRoamingEnabled has a default value of false.
// kAccountsPrefEphemeralUsersEnabled has a default value of false.
if (policy.has_allow_new_users() &&
policy.allow_new_users().has_allow_new_users() &&
policy.allow_new_users().allow_new_users()) {
// New users allowed, user_whitelist() ignored.
new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true);
} else if (!policy.has_user_whitelist()) {
// If we have the allow_new_users bool, and it is true, we honor that above.
// In all other cases (don't have it, have it and it is set to false, etc),
// We will honor the user_whitelist() if it is there and populated.
// Otherwise we default to allowing new users.
new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true);
} else {
new_values_cache->SetBoolean(
kAccountsPrefAllowNewUser,
policy.user_whitelist().user_whitelist_size() == 0);
}
new_values_cache->SetBoolean(
kAccountsPrefAllowGuest,
!policy.has_guest_mode_enabled() ||
!policy.guest_mode_enabled().has_guest_mode_enabled() ||
policy.guest_mode_enabled().guest_mode_enabled());
new_values_cache->SetBoolean(
kAccountsPrefShowUserNamesOnSignIn,
!policy.has_show_user_names() ||
!policy.show_user_names().has_show_user_names() ||
policy.show_user_names().show_user_names());
new_values_cache->SetBoolean(
kAccountsPrefEphemeralUsersEnabled,
policy.has_ephemeral_users_enabled() &&
policy.ephemeral_users_enabled().has_ephemeral_users_enabled() &&
policy.ephemeral_users_enabled().ephemeral_users_enabled());
base::ListValue* list = new base::ListValue();
const em::UserWhitelistProto& whitelist_proto = policy.user_whitelist();
const RepeatedPtrField<std::string>& whitelist =
whitelist_proto.user_whitelist();
for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
it != whitelist.end(); ++it) {
list->Append(base::Value::CreateStringValue(*it));
}
new_values_cache->SetValue(kAccountsPrefUsers, list);
}
void DeviceSettingsProvider::DecodeKioskPolicies(
const em::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const {
if (policy.has_forced_logout_timeouts()) {
if (policy.forced_logout_timeouts().has_idle_logout_timeout()) {
new_values_cache->SetInteger(
kIdleLogoutTimeout,
policy.forced_logout_timeouts().idle_logout_timeout());
}
if (policy.forced_logout_timeouts().has_idle_logout_warning_duration()) {
new_values_cache->SetInteger(
kIdleLogoutWarningDuration,
policy.forced_logout_timeouts().idle_logout_warning_duration());
}
}
if (policy.has_login_screen_saver()) {
if (policy.login_screen_saver().has_screen_saver_timeout()) {
new_values_cache->SetInteger(
kScreenSaverTimeout,
policy.login_screen_saver().screen_saver_timeout());
}
if (policy.login_screen_saver().has_screen_saver_extension_id()) {
new_values_cache->SetString(
kScreenSaverExtensionId,
policy.login_screen_saver().screen_saver_extension_id());
}
}
if (policy.has_app_pack()) {
typedef RepeatedPtrField<em::AppPackEntryProto> proto_type;
base::ListValue* list = new base::ListValue;
const proto_type& app_pack = policy.app_pack().app_pack();
for (proto_type::const_iterator it = app_pack.begin();
it != app_pack.end(); ++it) {
base::DictionaryValue* entry = new base::DictionaryValue;
if (it->has_extension_id()) {
entry->SetString(policy::AppPackUpdater::kExtensionId,
it->extension_id());
}
if (it->has_update_url())
entry->SetString(policy::AppPackUpdater::kUpdateUrl, it->update_url());
if (it->has_key_checksum()) {
entry->SetString(policy::AppPackUpdater::kKeyChecksum,
it->key_checksum());
}
list->Append(entry);
}
new_values_cache->SetValue(kAppPack, list);
}
}
void DeviceSettingsProvider::DecodeNetworkPolicies(
const em::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const {
new_values_cache->SetBoolean(
kSignedDataRoamingEnabled,
policy.has_data_roaming_enabled() &&
policy.data_roaming_enabled().has_data_roaming_enabled() &&
policy.data_roaming_enabled().data_roaming_enabled());
// TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed.
std::string serialized;
if (policy.has_device_proxy_settings() &&
policy.device_proxy_settings().SerializeToString(&serialized)) {
new_values_cache->SetString(kSettingProxyEverywhere, serialized);
}
}
void DeviceSettingsProvider::DecodeReportingPolicies(
const em::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const {
if (policy.has_device_reporting()) {
if (policy.device_reporting().has_report_version_info()) {
new_values_cache->SetBoolean(
kReportDeviceVersionInfo,
policy.device_reporting().report_version_info());
}
// TODO(dubroy): Re-add device activity time policy here when the UI
// to notify the user has been implemented (http://crosbug.com/26252).
if (policy.device_reporting().has_report_boot_mode()) {
new_values_cache->SetBoolean(
kReportDeviceBootMode,
policy.device_reporting().report_boot_mode());
}
}
}
void DeviceSettingsProvider::DecodeGenericPolicies(
const em::ChromeDeviceSettingsProto& policy,
PrefValueMap* new_values_cache) const {
if (policy.has_metrics_enabled()) {
new_values_cache->SetBoolean(kStatsReportingPref,
policy.metrics_enabled().metrics_enabled());
} else {
new_values_cache->SetBoolean(kStatsReportingPref, HasOldMetricsFile());
}
if (!policy.has_release_channel() ||
!policy.release_channel().has_release_channel()) {
// Default to an invalid channel (will be ignored).
new_values_cache->SetString(kReleaseChannel, "");
} else {
new_values_cache->SetString(kReleaseChannel,
policy.release_channel().release_channel());
}
}
void DeviceSettingsProvider::UpdateValuesCache() {
const em::PolicyData data = policy();
PrefValueMap new_values_cache;
if (data.has_username() && !data.has_request_token())
new_values_cache.SetString(kDeviceOwner, data.username());
em::ChromeDeviceSettingsProto pol;
pol.ParseFromString(data.policy_value());
DecodeLoginPolicies(pol, &new_values_cache);
DecodeKioskPolicies(pol, &new_values_cache);
DecodeNetworkPolicies(pol, &new_values_cache);
DecodeReportingPolicies(pol, &new_values_cache);
DecodeGenericPolicies(pol, &new_values_cache);
// Collect all notifications but send them only after we have swapped the
// cache so that if somebody actually reads the cache will be already valid.
std::vector<std::string> notifications;
// Go through the new values and verify in the old ones.
PrefValueMap::iterator iter = new_values_cache.begin();
for (; iter != new_values_cache.end(); ++iter) {
const base::Value* old_value;
if (!values_cache_.GetValue(iter->first, &old_value) ||
!old_value->Equals(iter->second)) {
notifications.push_back(iter->first);
}
}
// Now check for values that have been removed from the policy blob.
for (iter = values_cache_.begin(); iter != values_cache_.end(); ++iter) {
const base::Value* value;
if (!new_values_cache.GetValue(iter->first, &value))
notifications.push_back(iter->first);
}
// Swap and notify.
values_cache_.Swap(&new_values_cache);
for (size_t i = 0; i < notifications.size(); ++i)
NotifyObservers(notifications[i]);
}
void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file,
bool new_value) const {
// TODO(pastarmovj): Remove this once migration is not needed anymore.
// If the value is not set we should try to migrate legacy consent file.
if (use_file) {
new_value = HasOldMetricsFile();
// Make sure the values will get eventually written to the policy file.
migration_helper_->AddMigrationValue(
kStatsReportingPref, base::Value::CreateBooleanValue(new_value));
migration_helper_->MigrateValues();
LOG(INFO) << "No metrics policy set will revert to checking "
<< "consent file which is "
<< (new_value ? "on." : "off.");
}
VLOG(1) << "Metrics policy is being set to : " << new_value
<< "(use file : " << use_file << ")";
// TODO(pastarmovj): Remove this once we don't need to regenerate the
// consent file for the GUID anymore.
OptionsUtil::ResolveMetricsReportingEnabled(new_value);
}
void DeviceSettingsProvider::ApplyRoamingSetting(bool new_value) const {
NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
const NetworkDevice* cellular = cros->FindCellularDevice();
if (cellular) {
bool device_value = cellular->data_roaming_allowed();
if (!device_value && cros->IsCellularAlwaysInRoaming()) {
// If operator requires roaming always enabled, ignore supplied value
// and set data roaming allowed in true always.
cros->SetCellularDataRoamingAllowed(true);
} else if (device_value != new_value) {
cros->SetCellularDataRoamingAllowed(new_value);
}
}
}
void DeviceSettingsProvider::ApplySideEffects() const {
const em::PolicyData data = policy();
em::ChromeDeviceSettingsProto pol;
pol.ParseFromString(data.policy_value());
// First migrate metrics settings as needed.
if (pol.has_metrics_enabled())
ApplyMetricsSetting(false, pol.metrics_enabled().metrics_enabled());
else
ApplyMetricsSetting(true, false);
// Next set the roaming setting as needed.
ApplyRoamingSetting(pol.has_data_roaming_enabled() ?
pol.data_roaming_enabled().data_roaming_enabled() : false);
}
bool DeviceSettingsProvider::MitigateMissingPolicy() {
// As this code runs only in exceptional cases it's fine to allow I/O here.
base::ThreadRestrictions::ScopedAllowIO allow_io;
FilePath legacy_policy_file(kLegacyPolicyFile);
// Check if legacy file exists but is not writable to avoid possible
// attack of creating this file through chronos (although this should be
// not possible in root owned location), but better be safe than sorry.
// TODO(pastarmovj): Remove this workaround once we have proper checking
// for policy corruption or when Cr48 is phased out the very latest.
// See: http://crosbug.com/24916.
if (file_util::PathExists(legacy_policy_file) &&
!file_util::PathIsWritable(legacy_policy_file)) {
// We are in pre 11 dev upgrading to post 17 version mode.
LOG(ERROR) << "Detected system upgraded from ChromeOS 11 or older with "
<< "missing policies. Switching to migration policy mode "
<< "until the owner logs in to regenerate the policy data.";
// In this situation we should pretend we have policy even though we
// don't until the owner logs in and restores the policy blob.
values_cache_.SetBoolean(kAccountsPrefAllowNewUser, true);
values_cache_.SetBoolean(kAccountsPrefAllowGuest, true);
trusted_ = true;
// Make sure we will recreate the policy once the owner logs in.
// Any value not in this list will be left to the default which is fine as
// we repopulate the whitelist with the owner and any other possible every
// time the user enables whitelist filtering on the UI.
migration_helper_->AddMigrationValue(
kAccountsPrefAllowNewUser, base::Value::CreateBooleanValue(true));
migration_helper_->MigrateValues();
// The last step is to pretend we loaded policy correctly and call everyone.
for (size_t i = 0; i < callbacks_.size(); ++i)
callbacks_[i].Run();
callbacks_.clear();
return true;
}
return false;
}
const base::Value* DeviceSettingsProvider::Get(const std::string& path) const {
if (IsControlledSetting(path)) {
const base::Value* value;
if (values_cache_.GetValue(path, &value))
return value;
} else {
NOTREACHED() << "Trying to get non cros setting.";
}
return NULL;
}
bool DeviceSettingsProvider::GetTrusted(const std::string& path,
const base::Closure& callback) {
if (!IsControlledSetting(path)) {
NOTREACHED();
return true;
}
if (RequestTrustedEntity()) {
return true;
} else {
if (!callback.is_null())
callbacks_.push_back(callback);
return false;
}
}
bool DeviceSettingsProvider::HandlesSetting(const std::string& path) const {
return IsControlledSetting(path);
}
bool DeviceSettingsProvider::RequestTrustedEntity() {
if (ownership_status_ == OwnershipService::OWNERSHIP_NONE)
return true;
return trusted_;
}
void DeviceSettingsProvider::OnStorePolicyCompleted(
SignedSettings::ReturnCode code) {
// In any case reload the policy cache to now.
if (code != SignedSettings::SUCCESS)
Reload();
else
trusted_ = true;
// Clear the finished task and proceed with any other stores that could be
// pending by now.
delete pending_changes_[0].second;
pending_changes_.erase(pending_changes_.begin());
if (!pending_changes_.empty())
SetInPolicy();
}
void DeviceSettingsProvider::OnRetrievePolicyCompleted(
SignedSettings::ReturnCode code,
const em::PolicyFetchResponse& policy_data) {
VLOG(1) << "OnRetrievePolicyCompleted. Error code: " << code
<< ", trusted : " << trusted_ << ", status : " << ownership_status_;
switch (code) {
case SignedSettings::SUCCESS: {
DCHECK(policy_data.has_policy_data());
policy_.ParseFromString(policy_data.policy_data());
signed_settings_cache::Store(policy(),
g_browser_process->local_state());
UpdateValuesCache();
trusted_ = true;
for (size_t i = 0; i < callbacks_.size(); ++i)
callbacks_[i].Run();
callbacks_.clear();
// TODO(pastarmovj): Make those side effects responsibility of the
// respective subsystems.
ApplySideEffects();
break;
}
case SignedSettings::NOT_FOUND:
// Verify if we don't have to mitigate pre Chrome 12 machine here and if
// needed do the magic.
if (MitigateMissingPolicy())
break;
case SignedSettings::KEY_UNAVAILABLE: {
if (ownership_status_ != OwnershipService::OWNERSHIP_TAKEN)
NOTREACHED() << "No policies present yet, will use the temp storage.";
break;
}
case SignedSettings::BAD_SIGNATURE:
case SignedSettings::OPERATION_FAILED: {
LOG(ERROR) << "Failed to retrieve cros policies. Reason:" << code;
if (retries_left_ > 0) {
retries_left_ -= 1;
Reload();
return;
}
LOG(ERROR) << "No retries left";
break;
}
}
}
} // namespace chromeos