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