device_settings_provider.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/file_util.h"
11#include "base/logging.h"
12#include "base/string_util.h"
13#include "base/threading/thread_restrictions.h"
14#include "base/values.h"
15#include "chrome/browser/browser_process.h"
16#include "chrome/browser/chromeos/cros/cros_library.h"
17#include "chrome/browser/chromeos/cros/network_library.h"
18#include "chrome/browser/chromeos/settings/cros_settings.h"
19#include "chrome/browser/chromeos/settings/cros_settings_names.h"
20#include "chrome/browser/chromeos/settings/device_settings_cache.h"
21#include "chrome/browser/policy/app_pack_updater.h"
22#include "chrome/browser/policy/browser_policy_connector.h"
23#include "chrome/browser/policy/cloud_policy_constants.h"
24#include "chrome/browser/policy/proto/device_management_backend.pb.h"
25#include "chrome/browser/ui/options/options_util.h"
26#include "chrome/installer/util/google_update_settings.h"
27
28using google::protobuf::RepeatedPtrField;
29
30namespace em = enterprise_management;
31
32namespace chromeos {
33
34namespace {
35
36// List of settings handled by the DeviceSettingsProvider.
37const char* kKnownSettings[] = {
38  kAccountsPrefAllowGuest,
39  kAccountsPrefAllowNewUser,
40  kAccountsPrefEphemeralUsersEnabled,
41  kAccountsPrefShowUserNamesOnSignIn,
42  kAccountsPrefUsers,
43  kAppPack,
44  kDeviceOwner,
45  kIdleLogoutTimeout,
46  kIdleLogoutWarningDuration,
47  kPolicyMissingMitigationMode,
48  kReleaseChannel,
49  kReleaseChannelDelegated,
50  kReportDeviceActivityTimes,
51  kReportDeviceBootMode,
52  kReportDeviceLocation,
53  kReportDeviceVersionInfo,
54  kScreenSaverExtensionId,
55  kScreenSaverTimeout,
56  kSettingProxyEverywhere,
57  kSignedDataRoamingEnabled,
58  kStartUpUrls,
59  kStatsReportingPref,
60  kSystemTimezonePolicy,
61};
62
63// Legacy policy file location. Used to detect migration from pre v12 ChromeOS.
64const char kLegacyPolicyFile[] = "/var/lib/whitelist/preferences";
65
66bool IsControlledSetting(const std::string& pref_path) {
67  const char** end = kKnownSettings + arraysize(kKnownSettings);
68  return std::find(kKnownSettings, end, pref_path) != end;
69}
70
71bool HasOldMetricsFile() {
72  // TODO(pastarmovj): Remove this once migration is not needed anymore.
73  // If the value is not set we should try to migrate legacy consent file.
74  // Loading consent file state causes us to do blocking IO on UI thread.
75  // Temporarily allow it until we fix http://crbug.com/62626
76  base::ThreadRestrictions::ScopedAllowIO allow_io;
77  return GoogleUpdateSettings::GetCollectStatsConsent();
78}
79
80}  // namespace
81
82DeviceSettingsProvider::DeviceSettingsProvider(
83    const NotifyObserversCallback& notify_cb,
84    DeviceSettingsService* device_settings_service)
85    : CrosSettingsProvider(notify_cb),
86      device_settings_service_(device_settings_service),
87      trusted_status_(TEMPORARILY_UNTRUSTED),
88      ownership_status_(device_settings_service_->GetOwnershipStatus()),
89      ALLOW_THIS_IN_INITIALIZER_LIST(store_callback_factory_(this)) {
90  device_settings_service_->AddObserver(this);
91
92  if (!UpdateFromService()) {
93    // Make sure we have at least the cache data immediately.
94    RetrieveCachedData();
95  }
96}
97
98DeviceSettingsProvider::~DeviceSettingsProvider() {
99  device_settings_service_->RemoveObserver(this);
100}
101
102void DeviceSettingsProvider::DoSet(const std::string& path,
103                                   const base::Value& in_value) {
104  // Make sure that either the current user is the device owner or the
105  // device doesn't have an owner yet.
106  if (!(device_settings_service_->HasPrivateOwnerKey() ||
107        ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)) {
108    LOG(WARNING) << "Changing settings from non-owner, setting=" << path;
109
110    // Revert UI change.
111    NotifyObservers(path);
112    return;
113  }
114
115  if (IsControlledSetting(path)) {
116    pending_changes_.push_back(PendingQueueElement(path, in_value.DeepCopy()));
117    if (!store_callback_factory_.HasWeakPtrs())
118      SetInPolicy();
119  } else {
120    NOTREACHED() << "Try to set unhandled cros setting " << path;
121  }
122}
123
124void DeviceSettingsProvider::OwnershipStatusChanged() {
125  DeviceSettingsService::OwnershipStatus new_ownership_status =
126      device_settings_service_->GetOwnershipStatus();
127
128  // If the device just became owned, write the settings accumulated in the
129  // cache to device settings proper. It is important that writing only happens
130  // in this case, as during normal operation, the contents of the cache should
131  // never overwrite actual device settings.
132  if (new_ownership_status == DeviceSettingsService::OWNERSHIP_TAKEN &&
133      ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE &&
134      device_settings_service_->HasPrivateOwnerKey()) {
135
136    // There shouldn't be any pending writes, since the cache writes are all
137    // immediate.
138    DCHECK(!store_callback_factory_.HasWeakPtrs());
139
140    // Apply the locally-accumulated device settings on top of the initial
141    // settings from the service and write back the result.
142    if (device_settings_service_->device_settings()) {
143      em::ChromeDeviceSettingsProto new_settings(
144          *device_settings_service_->device_settings());
145      new_settings.MergeFrom(device_settings_);
146      device_settings_.Swap(&new_settings);
147    }
148    StoreDeviceSettings();
149  }
150
151  // The owner key might have become available, allowing migration to happen.
152  AttemptMigration();
153
154  ownership_status_ = new_ownership_status;
155}
156
157void DeviceSettingsProvider::DeviceSettingsUpdated() {
158  if (!store_callback_factory_.HasWeakPtrs())
159    UpdateAndProceedStoring();
160}
161
162void DeviceSettingsProvider::RetrieveCachedData() {
163  em::PolicyData policy_data;
164  if (!device_settings_cache::Retrieve(&policy_data,
165                                       g_browser_process->local_state()) ||
166      !device_settings_.ParseFromString(policy_data.policy_value())) {
167    VLOG(1) << "Can't retrieve temp store, possibly not created yet.";
168  }
169
170  UpdateValuesCache(policy_data, device_settings_);
171}
172
173void DeviceSettingsProvider::SetInPolicy() {
174  if (pending_changes_.empty()) {
175    NOTREACHED();
176    return;
177  }
178
179  if (RequestTrustedEntity() != TRUSTED) {
180    // Re-sync device settings before proceeding.
181    device_settings_service_->Load();
182    return;
183  }
184
185  std::string prop(pending_changes_.front().first);
186  scoped_ptr<base::Value> value(pending_changes_.front().second);
187  pending_changes_.pop_front();
188
189  trusted_status_ = TEMPORARILY_UNTRUSTED;
190  if (prop == kAccountsPrefAllowNewUser) {
191    em::AllowNewUsersProto* allow =
192        device_settings_.mutable_allow_new_users();
193    bool allow_value;
194    if (value->GetAsBoolean(&allow_value))
195      allow->set_allow_new_users(allow_value);
196    else
197      NOTREACHED();
198  } else if (prop == kAccountsPrefAllowGuest) {
199    em::GuestModeEnabledProto* guest =
200        device_settings_.mutable_guest_mode_enabled();
201    bool guest_value;
202    if (value->GetAsBoolean(&guest_value))
203      guest->set_guest_mode_enabled(guest_value);
204    else
205      NOTREACHED();
206  } else if (prop == kAccountsPrefShowUserNamesOnSignIn) {
207    em::ShowUserNamesOnSigninProto* show =
208        device_settings_.mutable_show_user_names();
209    bool show_value;
210    if (value->GetAsBoolean(&show_value))
211      show->set_show_user_names(show_value);
212    else
213      NOTREACHED();
214  } else if (prop == kSignedDataRoamingEnabled) {
215    em::DataRoamingEnabledProto* roam =
216        device_settings_.mutable_data_roaming_enabled();
217    bool roaming_value = false;
218    if (value->GetAsBoolean(&roaming_value))
219      roam->set_data_roaming_enabled(roaming_value);
220    else
221      NOTREACHED();
222    ApplyRoamingSetting(roaming_value);
223  } else if (prop == kSettingProxyEverywhere) {
224    // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed.
225    std::string proxy_value;
226    if (value->GetAsString(&proxy_value)) {
227      bool success =
228          device_settings_.mutable_device_proxy_settings()->ParseFromString(
229              proxy_value);
230      DCHECK(success);
231    } else {
232      NOTREACHED();
233    }
234  } else if (prop == kReleaseChannel) {
235    em::ReleaseChannelProto* release_channel =
236        device_settings_.mutable_release_channel();
237    std::string channel_value;
238    if (value->GetAsString(&channel_value))
239      release_channel->set_release_channel(channel_value);
240    else
241      NOTREACHED();
242  } else if (prop == kStatsReportingPref) {
243    em::MetricsEnabledProto* metrics =
244        device_settings_.mutable_metrics_enabled();
245    bool metrics_value = false;
246    if (value->GetAsBoolean(&metrics_value))
247      metrics->set_metrics_enabled(metrics_value);
248    else
249      NOTREACHED();
250    ApplyMetricsSetting(false, metrics_value);
251  } else if (prop == kAccountsPrefUsers) {
252    em::UserWhitelistProto* whitelist_proto =
253        device_settings_.mutable_user_whitelist();
254    whitelist_proto->clear_user_whitelist();
255    base::ListValue& users = static_cast<base::ListValue&>(*value);
256    for (base::ListValue::const_iterator i = users.begin();
257         i != users.end(); ++i) {
258      std::string email;
259      if ((*i)->GetAsString(&email))
260        whitelist_proto->add_user_whitelist(email.c_str());
261    }
262  } else if (prop == kAccountsPrefEphemeralUsersEnabled) {
263    em::EphemeralUsersEnabledProto* ephemeral_users_enabled =
264        device_settings_.mutable_ephemeral_users_enabled();
265    bool ephemeral_users_enabled_value = false;
266    if (value->GetAsBoolean(&ephemeral_users_enabled_value)) {
267      ephemeral_users_enabled->set_ephemeral_users_enabled(
268          ephemeral_users_enabled_value);
269    } else {
270      NOTREACHED();
271    }
272  } else {
273    // The remaining settings don't support Set(), since they are not
274    // intended to be customizable by the user:
275    //   kAppPack
276    //   kDeviceOwner
277    //   kIdleLogoutTimeout
278    //   kIdleLogoutWarningDuration
279    //   kReleaseChannelDelegated
280    //   kReportDeviceVersionInfo
281    //   kReportDeviceActivityTimes
282    //   kReportDeviceBootMode
283    //   kReportDeviceLocation
284    //   kScreenSaverExtensionId
285    //   kScreenSaverTimeout
286    //   kStartUpUrls
287    //   kSystemTimezonePolicy
288
289    LOG(FATAL) << "Device setting " << prop << " is read-only.";
290  }
291
292  em::PolicyData data;
293  data.set_username(device_settings_service_->GetUsername());
294  CHECK(device_settings_.SerializeToString(data.mutable_policy_value()));
295
296  // Set the cache to the updated value.
297  UpdateValuesCache(data, device_settings_);
298
299  if (!device_settings_cache::Store(data, g_browser_process->local_state()))
300    LOG(ERROR) << "Couldn't store to the temp storage.";
301
302  if (ownership_status_ == DeviceSettingsService::OWNERSHIP_TAKEN) {
303    StoreDeviceSettings();
304  } else {
305    // OnStorePolicyCompleted won't get called in this case so proceed with any
306    // pending operations immediately.
307    if (!pending_changes_.empty())
308      SetInPolicy();
309  }
310}
311
312void DeviceSettingsProvider::DecodeLoginPolicies(
313    const em::ChromeDeviceSettingsProto& policy,
314    PrefValueMap* new_values_cache) const {
315  // For all our boolean settings the following is applicable:
316  // true is default permissive value and false is safe prohibitive value.
317  // Exceptions:
318  //   kSignedDataRoamingEnabled has a default value of false.
319  //   kAccountsPrefEphemeralUsersEnabled has a default value of false.
320  if (policy.has_allow_new_users() &&
321      policy.allow_new_users().has_allow_new_users() &&
322      policy.allow_new_users().allow_new_users()) {
323    // New users allowed, user_whitelist() ignored.
324    new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true);
325  } else if (!policy.has_user_whitelist()) {
326    // If we have the allow_new_users bool, and it is true, we honor that above.
327    // In all other cases (don't have it, have it and it is set to false, etc),
328    // We will honor the user_whitelist() if it is there and populated.
329    // Otherwise we default to allowing new users.
330    new_values_cache->SetBoolean(kAccountsPrefAllowNewUser, true);
331  } else {
332    new_values_cache->SetBoolean(
333        kAccountsPrefAllowNewUser,
334        policy.user_whitelist().user_whitelist_size() == 0);
335  }
336
337  new_values_cache->SetBoolean(
338      kAccountsPrefAllowGuest,
339      !policy.has_guest_mode_enabled() ||
340      !policy.guest_mode_enabled().has_guest_mode_enabled() ||
341      policy.guest_mode_enabled().guest_mode_enabled());
342
343  new_values_cache->SetBoolean(
344      kAccountsPrefShowUserNamesOnSignIn,
345      !policy.has_show_user_names() ||
346      !policy.show_user_names().has_show_user_names() ||
347      policy.show_user_names().show_user_names());
348
349  new_values_cache->SetBoolean(
350      kAccountsPrefEphemeralUsersEnabled,
351      policy.has_ephemeral_users_enabled() &&
352      policy.ephemeral_users_enabled().has_ephemeral_users_enabled() &&
353      policy.ephemeral_users_enabled().ephemeral_users_enabled());
354
355  base::ListValue* list = new base::ListValue();
356  const em::UserWhitelistProto& whitelist_proto = policy.user_whitelist();
357  const RepeatedPtrField<std::string>& whitelist =
358      whitelist_proto.user_whitelist();
359  for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
360       it != whitelist.end(); ++it) {
361    list->Append(base::Value::CreateStringValue(*it));
362  }
363  new_values_cache->SetValue(kAccountsPrefUsers, list);
364}
365
366void DeviceSettingsProvider::DecodeKioskPolicies(
367    const em::ChromeDeviceSettingsProto& policy,
368    PrefValueMap* new_values_cache) const {
369  if (policy.has_forced_logout_timeouts()) {
370    if (policy.forced_logout_timeouts().has_idle_logout_timeout()) {
371      new_values_cache->SetInteger(
372          kIdleLogoutTimeout,
373          policy.forced_logout_timeouts().idle_logout_timeout());
374    }
375
376    if (policy.forced_logout_timeouts().has_idle_logout_warning_duration()) {
377      new_values_cache->SetInteger(
378          kIdleLogoutWarningDuration,
379          policy.forced_logout_timeouts().idle_logout_warning_duration());
380    }
381  }
382
383  if (policy.has_login_screen_saver()) {
384    if (policy.login_screen_saver().has_screen_saver_timeout()) {
385      new_values_cache->SetInteger(
386          kScreenSaverTimeout,
387          policy.login_screen_saver().screen_saver_timeout());
388    }
389
390    if (policy.login_screen_saver().has_screen_saver_extension_id()) {
391      new_values_cache->SetString(
392          kScreenSaverExtensionId,
393          policy.login_screen_saver().screen_saver_extension_id());
394    }
395  }
396
397  if (policy.has_app_pack()) {
398    typedef RepeatedPtrField<em::AppPackEntryProto> proto_type;
399    base::ListValue* list = new base::ListValue;
400    const proto_type& app_pack = policy.app_pack().app_pack();
401    for (proto_type::const_iterator it = app_pack.begin();
402         it != app_pack.end(); ++it) {
403      base::DictionaryValue* entry = new base::DictionaryValue;
404      if (it->has_extension_id()) {
405        entry->SetString(policy::AppPackUpdater::kExtensionId,
406                         it->extension_id());
407      }
408      if (it->has_update_url())
409        entry->SetString(policy::AppPackUpdater::kUpdateUrl, it->update_url());
410      list->Append(entry);
411    }
412    new_values_cache->SetValue(kAppPack, list);
413  }
414
415  if (policy.has_start_up_urls()) {
416    base::ListValue* list = new base::ListValue();
417    const em::StartUpUrlsProto& urls_proto = policy.start_up_urls();
418    const RepeatedPtrField<std::string>& urls = urls_proto.start_up_urls();
419    for (RepeatedPtrField<std::string>::const_iterator it = urls.begin();
420         it != urls.end(); ++it) {
421      list->Append(base::Value::CreateStringValue(*it));
422    }
423    new_values_cache->SetValue(kStartUpUrls, list);
424  }
425}
426
427void DeviceSettingsProvider::DecodeNetworkPolicies(
428    const em::ChromeDeviceSettingsProto& policy,
429    PrefValueMap* new_values_cache) const {
430  new_values_cache->SetBoolean(
431      kSignedDataRoamingEnabled,
432      policy.has_data_roaming_enabled() &&
433      policy.data_roaming_enabled().has_data_roaming_enabled() &&
434      policy.data_roaming_enabled().data_roaming_enabled());
435
436  // TODO(cmasone): NOTIMPLEMENTED() once http://crosbug.com/13052 is fixed.
437  std::string serialized;
438  if (policy.has_device_proxy_settings() &&
439      policy.device_proxy_settings().SerializeToString(&serialized)) {
440    new_values_cache->SetString(kSettingProxyEverywhere, serialized);
441  }
442}
443
444void DeviceSettingsProvider::DecodeReportingPolicies(
445    const em::ChromeDeviceSettingsProto& policy,
446    PrefValueMap* new_values_cache) const {
447  if (policy.has_device_reporting()) {
448    if (policy.device_reporting().has_report_version_info()) {
449      new_values_cache->SetBoolean(
450          kReportDeviceVersionInfo,
451          policy.device_reporting().report_version_info());
452    }
453    if (policy.device_reporting().has_report_activity_times()) {
454      new_values_cache->SetBoolean(
455          kReportDeviceActivityTimes,
456          policy.device_reporting().report_activity_times());
457    }
458    if (policy.device_reporting().has_report_boot_mode()) {
459      new_values_cache->SetBoolean(
460          kReportDeviceBootMode,
461          policy.device_reporting().report_boot_mode());
462    }
463    // Device location reporting needs to pass privacy review before it can be
464    // enabled. crosbug.com/24681
465    // if (policy.device_reporting().has_report_location()) {
466    //   new_values_cache->SetBoolean(
467    //       kReportDeviceLocation,
468    //       policy.device_reporting().report_location());
469    // }
470  }
471}
472
473void DeviceSettingsProvider::DecodeGenericPolicies(
474    const em::ChromeDeviceSettingsProto& policy,
475    PrefValueMap* new_values_cache) const {
476  if (policy.has_metrics_enabled()) {
477    new_values_cache->SetBoolean(kStatsReportingPref,
478                                 policy.metrics_enabled().metrics_enabled());
479  } else {
480    new_values_cache->SetBoolean(kStatsReportingPref, HasOldMetricsFile());
481  }
482
483  if (!policy.has_release_channel() ||
484      !policy.release_channel().has_release_channel()) {
485    // Default to an invalid channel (will be ignored).
486    new_values_cache->SetString(kReleaseChannel, "");
487  } else {
488    new_values_cache->SetString(kReleaseChannel,
489                                policy.release_channel().release_channel());
490  }
491
492  new_values_cache->SetBoolean(
493      kReleaseChannelDelegated,
494      policy.has_release_channel() &&
495      policy.release_channel().has_release_channel_delegated() &&
496      policy.release_channel().release_channel_delegated());
497
498  if (policy.has_system_timezone()) {
499    if (policy.system_timezone().has_timezone()) {
500      new_values_cache->SetString(
501          kSystemTimezonePolicy,
502          policy.system_timezone().timezone());
503    }
504  }
505}
506
507void DeviceSettingsProvider::UpdateValuesCache(
508    const em::PolicyData& policy_data,
509    const em::ChromeDeviceSettingsProto& settings) {
510  PrefValueMap new_values_cache;
511
512  if (policy_data.has_username() && !policy_data.has_request_token())
513    new_values_cache.SetString(kDeviceOwner, policy_data.username());
514
515  DecodeLoginPolicies(settings, &new_values_cache);
516  DecodeKioskPolicies(settings, &new_values_cache);
517  DecodeNetworkPolicies(settings, &new_values_cache);
518  DecodeReportingPolicies(settings, &new_values_cache);
519  DecodeGenericPolicies(settings, &new_values_cache);
520
521  // Collect all notifications but send them only after we have swapped the
522  // cache so that if somebody actually reads the cache will be already valid.
523  std::vector<std::string> notifications;
524  // Go through the new values and verify in the old ones.
525  PrefValueMap::iterator iter = new_values_cache.begin();
526  for (; iter != new_values_cache.end(); ++iter) {
527    const base::Value* old_value;
528    if (!values_cache_.GetValue(iter->first, &old_value) ||
529        !old_value->Equals(iter->second)) {
530      notifications.push_back(iter->first);
531    }
532  }
533  // Now check for values that have been removed from the policy blob.
534  for (iter = values_cache_.begin(); iter != values_cache_.end(); ++iter) {
535    const base::Value* value;
536    if (!new_values_cache.GetValue(iter->first, &value))
537      notifications.push_back(iter->first);
538  }
539  // Swap and notify.
540  values_cache_.Swap(&new_values_cache);
541  for (size_t i = 0; i < notifications.size(); ++i)
542    NotifyObservers(notifications[i]);
543}
544
545void DeviceSettingsProvider::ApplyMetricsSetting(bool use_file,
546                                                 bool new_value) {
547  // TODO(pastarmovj): Remove this once migration is not needed anymore.
548  // If the value is not set we should try to migrate legacy consent file.
549  if (use_file) {
550    new_value = HasOldMetricsFile();
551    // Make sure the values will get eventually written to the policy file.
552    migration_values_.SetValue(kStatsReportingPref,
553                               base::Value::CreateBooleanValue(new_value));
554    AttemptMigration();
555    LOG(INFO) << "No metrics policy set will revert to checking "
556              << "consent file which is "
557              << (new_value ? "on." : "off.");
558  }
559  VLOG(1) << "Metrics policy is being set to : " << new_value
560          << "(use file : " << use_file << ")";
561  // TODO(pastarmovj): Remove this once we don't need to regenerate the
562  // consent file for the GUID anymore.
563  OptionsUtil::ResolveMetricsReportingEnabled(new_value);
564}
565
566void DeviceSettingsProvider::ApplyRoamingSetting(bool new_value) {
567  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
568  const NetworkDevice* cellular = cros->FindCellularDevice();
569  if (cellular) {
570    bool device_value = cellular->data_roaming_allowed();
571    if (!device_value && cros->IsCellularAlwaysInRoaming()) {
572      // If operator requires roaming always enabled, ignore supplied value
573      // and set data roaming allowed in true always.
574      cros->SetCellularDataRoamingAllowed(true);
575    } else if (device_value != new_value) {
576      cros->SetCellularDataRoamingAllowed(new_value);
577    }
578  }
579}
580
581void DeviceSettingsProvider::ApplySideEffects(
582    const em::ChromeDeviceSettingsProto& settings) {
583  // First migrate metrics settings as needed.
584  if (settings.has_metrics_enabled())
585    ApplyMetricsSetting(false, settings.metrics_enabled().metrics_enabled());
586  else
587    ApplyMetricsSetting(true, false);
588
589  // Next set the roaming setting as needed.
590  ApplyRoamingSetting(
591      settings.has_data_roaming_enabled() ?
592          settings.data_roaming_enabled().data_roaming_enabled() :
593          false);
594}
595
596bool DeviceSettingsProvider::MitigateMissingPolicy() {
597  // First check if the device has been owned already and if not exit
598  // immediately.
599  if (g_browser_process->browser_policy_connector()->GetDeviceMode() !=
600          policy::DEVICE_MODE_CONSUMER) {
601    return false;
602  }
603
604  // If we are here the policy file were corrupted or missing. This can happen
605  // because we are migrating Pre R11 device to the new secure policies or there
606  // was an attempt to circumvent policy system. In this case we should populate
607  // the policy cache with "safe-mode" defaults which should allow the owner to
608  // log in but lock the device for anyone else until the policy blob has been
609  // recreated by the session manager.
610  LOG(ERROR) << "Corruption of the policy data has been detected."
611             << "Switching to \"safe-mode\" policies until the owner logs in "
612             << "to regenerate the policy data.";
613
614  device_settings_.Clear();
615  device_settings_.mutable_allow_new_users()->set_allow_new_users(true);
616  device_settings_.mutable_guest_mode_enabled()->set_guest_mode_enabled(true);
617  em::PolicyData empty_policy_data;
618  UpdateValuesCache(empty_policy_data, device_settings_);
619  values_cache_.SetBoolean(kPolicyMissingMitigationMode, true);
620  trusted_status_ = TRUSTED;
621
622  return true;
623}
624
625const base::Value* DeviceSettingsProvider::Get(const std::string& path) const {
626  if (IsControlledSetting(path)) {
627    const base::Value* value;
628    if (values_cache_.GetValue(path, &value))
629      return value;
630  } else {
631    NOTREACHED() << "Trying to get non cros setting.";
632  }
633
634  return NULL;
635}
636
637DeviceSettingsProvider::TrustedStatus
638    DeviceSettingsProvider::PrepareTrustedValues(const base::Closure& cb) {
639  TrustedStatus status = RequestTrustedEntity();
640  if (status == TEMPORARILY_UNTRUSTED && !cb.is_null())
641    callbacks_.push_back(cb);
642  return status;
643}
644
645bool DeviceSettingsProvider::HandlesSetting(const std::string& path) const {
646  return IsControlledSetting(path);
647}
648
649DeviceSettingsProvider::TrustedStatus
650    DeviceSettingsProvider::RequestTrustedEntity() {
651  if (ownership_status_ == DeviceSettingsService::OWNERSHIP_NONE)
652    return TRUSTED;
653  return trusted_status_;
654}
655
656void DeviceSettingsProvider::UpdateAndProceedStoring() {
657  // Re-sync the cache from the service.
658  UpdateFromService();
659
660  // Trigger the next change if necessary.
661  if (trusted_status_ == TRUSTED && !pending_changes_.empty())
662    SetInPolicy();
663}
664
665bool DeviceSettingsProvider::UpdateFromService() {
666  bool settings_loaded = false;
667  switch (device_settings_service_->status()) {
668    case DeviceSettingsService::STORE_SUCCESS: {
669      const em::PolicyData* policy_data =
670          device_settings_service_->policy_data();
671      const em::ChromeDeviceSettingsProto* device_settings =
672          device_settings_service_->device_settings();
673      if (policy_data && device_settings) {
674        UpdateValuesCache(*policy_data, *device_settings);
675        device_settings_ = *device_settings;
676        trusted_status_ = TRUSTED;
677
678        // TODO(pastarmovj): Make those side effects responsibility of the
679        // respective subsystems.
680        ApplySideEffects(*device_settings);
681
682        settings_loaded = true;
683      } else {
684        // Initial policy load is still pending.
685        trusted_status_ = TEMPORARILY_UNTRUSTED;
686      }
687      break;
688    }
689    case DeviceSettingsService::STORE_NO_POLICY:
690      if (MitigateMissingPolicy())
691        break;
692      // fall through.
693    case DeviceSettingsService::STORE_KEY_UNAVAILABLE:
694      VLOG(1) << "No policies present yet, will use the temp storage.";
695      trusted_status_ = PERMANENTLY_UNTRUSTED;
696      break;
697    case DeviceSettingsService::STORE_POLICY_ERROR:
698    case DeviceSettingsService::STORE_VALIDATION_ERROR:
699    case DeviceSettingsService::STORE_INVALID_POLICY:
700    case DeviceSettingsService::STORE_OPERATION_FAILED:
701      LOG(ERROR) << "Failed to retrieve cros policies. Reason: "
702                 << device_settings_service_->status();
703      trusted_status_ = PERMANENTLY_UNTRUSTED;
704      break;
705    case DeviceSettingsService::STORE_TEMP_VALIDATION_ERROR:
706      // The policy has failed to validate due to temporary error but it might
707      // take a long time until we recover so behave as it is a permanent error.
708      LOG(ERROR) << "Failed to retrieve cros policies because a temporary "
709                 << "validation error has occurred. Retrying might succeed.";
710      trusted_status_ = PERMANENTLY_UNTRUSTED;
711      break;
712  }
713
714  // Notify the observers we are done.
715  std::vector<base::Closure> callbacks;
716  callbacks.swap(callbacks_);
717  for (size_t i = 0; i < callbacks.size(); ++i)
718    callbacks[i].Run();
719
720  return settings_loaded;
721}
722
723void DeviceSettingsProvider::StoreDeviceSettings() {
724  // Mute all previous callbacks to guarantee the |pending_changes_| queue is
725  // processed serially.
726  store_callback_factory_.InvalidateWeakPtrs();
727
728  device_settings_service_->SignAndStore(
729      scoped_ptr<em::ChromeDeviceSettingsProto>(
730          new em::ChromeDeviceSettingsProto(device_settings_)),
731      base::Bind(&DeviceSettingsProvider::UpdateAndProceedStoring,
732                 store_callback_factory_.GetWeakPtr()));
733}
734
735void DeviceSettingsProvider::AttemptMigration() {
736  if (device_settings_service_->HasPrivateOwnerKey()) {
737    PrefValueMap::const_iterator i;
738    for (i = migration_values_.begin(); i != migration_values_.end(); ++i)
739      DoSet(i->first, *i->second);
740    migration_values_.Clear();
741  }
742}
743
744}  // namespace chromeos
745