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