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