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