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