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