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