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