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