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