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