device_policy_decoder_chromeos.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/policy/device_policy_decoder_chromeos.h"
6
7#include <limits>
8#include <string>
9
10#include "base/callback.h"
11#include "base/json/json_reader.h"
12#include "base/logging.h"
13#include "base/values.h"
14#include "chrome/browser/browser_process.h"
15#include "chrome/browser/chromeos/policy/device_local_account.h"
16#include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
17#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
18#include "chromeos/dbus/dbus_thread_manager.h"
19#include "chromeos/dbus/update_engine_client.h"
20#include "chromeos/settings/cros_settings_names.h"
21#include "components/policy/core/browser/browser_policy_connector.h"
22#include "components/policy/core/common/external_data_fetcher.h"
23#include "components/policy/core/common/policy_map.h"
24#include "components/policy/core/common/schema.h"
25#include "policy/policy_constants.h"
26#include "third_party/cros_system_api/dbus/service_constants.h"
27
28using google::protobuf::RepeatedField;
29using google::protobuf::RepeatedPtrField;
30
31namespace em = enterprise_management;
32
33namespace policy {
34
35namespace {
36
37// Decodes a protobuf integer to an IntegerValue. Returns NULL in case the input
38// value is out of bounds.
39scoped_ptr<base::Value> DecodeIntegerValue(google::protobuf::int64 value) {
40  if (value < std::numeric_limits<int>::min() ||
41      value > std::numeric_limits<int>::max()) {
42    LOG(WARNING) << "Integer value " << value
43                 << " out of numeric limits, ignoring.";
44    return scoped_ptr<base::Value>();
45  }
46
47  return scoped_ptr<base::Value>(
48      new base::FundamentalValue(static_cast<int>(value)));
49}
50
51// Decodes a JSON string to a base::Value, and drops unknown properties
52// according to a policy schema. |policy_name| is the name of a policy schema
53// defined in policy_templates.json. Returns NULL in case the input is not a
54// valid JSON string.
55scoped_ptr<base::Value> DecodeJsonStringAndDropUnknownBySchema(
56    const std::string& json_string,
57    const std::string& policy_name) {
58  std::string error;
59  base::Value* root(base::JSONReader::ReadAndReturnError(
60      json_string, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
61
62  if (!root) {
63    LOG(WARNING) << "Invalid JSON string: " << error << ", ignoring.";
64    return scoped_ptr<base::Value>();
65  }
66
67  const Schema& schema = g_browser_process
68                             ->browser_policy_connector()
69                             ->GetChromeSchema()
70                             .GetKnownProperty(policy_name);
71
72  if (schema.valid()) {
73    std::string error_path;
74    bool changed = false;
75
76    if (!schema.Normalize(
77            root, SCHEMA_ALLOW_UNKNOWN, &error_path, &error, &changed)) {
78      LOG(WARNING) << "Invalid policy value for " << policy_name << ": "
79                   << error << " at " << error_path << ".";
80      return scoped_ptr<base::Value>();
81    }
82
83    if (changed) {
84      LOG(WARNING) << "Some properties in " << policy_name
85                   << " were dropped: " << error << " at " << error_path << ".";
86    }
87  } else {
88    LOG(WARNING) << "Unknown or invalid policy schema for " << policy_name
89                 << ".";
90    return scoped_ptr<base::Value>();
91  }
92
93  return scoped_ptr<base::Value>(root);
94}
95
96base::Value* DecodeConnectionType(int value) {
97  static const char* const kConnectionTypes[] = {
98    shill::kTypeEthernet,
99    shill::kTypeWifi,
100    shill::kTypeWimax,
101    shill::kTypeBluetooth,
102    shill::kTypeCellular,
103  };
104
105  if (value < 0 || value >= static_cast<int>(arraysize(kConnectionTypes)))
106    return NULL;
107
108  return new base::StringValue(kConnectionTypes[value]);
109}
110
111void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy,
112                         PolicyMap* policies) {
113  if (policy.has_guest_mode_enabled()) {
114    const em::GuestModeEnabledProto& container(policy.guest_mode_enabled());
115    if (container.has_guest_mode_enabled()) {
116      policies->Set(key::kDeviceGuestModeEnabled,
117                    POLICY_LEVEL_MANDATORY,
118                    POLICY_SCOPE_MACHINE,
119                    new base::FundamentalValue(
120                        container.guest_mode_enabled()),
121                    NULL);
122    }
123  }
124
125  if (policy.has_show_user_names()) {
126    const em::ShowUserNamesOnSigninProto& container(policy.show_user_names());
127    if (container.has_show_user_names()) {
128      policies->Set(key::kDeviceShowUserNamesOnSignin,
129                    POLICY_LEVEL_MANDATORY,
130                    POLICY_SCOPE_MACHINE,
131                    new base::FundamentalValue(
132                        container.show_user_names()),
133                    NULL);
134    }
135  }
136
137  if (policy.has_allow_new_users()) {
138    const em::AllowNewUsersProto& container(policy.allow_new_users());
139    if (container.has_allow_new_users()) {
140      policies->Set(key::kDeviceAllowNewUsers,
141                    POLICY_LEVEL_MANDATORY,
142                    POLICY_SCOPE_MACHINE,
143                    new base::FundamentalValue(
144                        container.allow_new_users()),
145                    NULL);
146    }
147  }
148
149  if (policy.has_user_whitelist()) {
150    const em::UserWhitelistProto& container(policy.user_whitelist());
151    base::ListValue* whitelist = new base::ListValue();
152    RepeatedPtrField<std::string>::const_iterator entry;
153    for (entry = container.user_whitelist().begin();
154         entry != container.user_whitelist().end();
155         ++entry) {
156      whitelist->Append(new base::StringValue(*entry));
157    }
158    policies->Set(key::kDeviceUserWhitelist,
159                  POLICY_LEVEL_MANDATORY,
160                  POLICY_SCOPE_MACHINE,
161                  whitelist,
162                  NULL);
163  }
164
165  if (policy.has_ephemeral_users_enabled()) {
166    const em::EphemeralUsersEnabledProto& container(
167        policy.ephemeral_users_enabled());
168    if (container.has_ephemeral_users_enabled()) {
169      policies->Set(key::kDeviceEphemeralUsersEnabled,
170                    POLICY_LEVEL_MANDATORY,
171                    POLICY_SCOPE_MACHINE,
172                    new base::FundamentalValue(
173                        container.ephemeral_users_enabled()),
174                    NULL);
175    }
176  }
177
178  if (policy.has_device_local_accounts()) {
179    const em::DeviceLocalAccountsProto& container(
180        policy.device_local_accounts());
181    const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts =
182        container.account();
183    scoped_ptr<base::ListValue> account_list(new base::ListValue());
184    RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry;
185    for (entry = accounts.begin(); entry != accounts.end(); ++entry) {
186      scoped_ptr<base::DictionaryValue> entry_dict(
187          new base::DictionaryValue());
188      if (entry->has_type()) {
189        if (entry->has_account_id()) {
190          entry_dict->SetStringWithoutPathExpansion(
191              chromeos::kAccountsPrefDeviceLocalAccountsKeyId,
192              entry->account_id());
193        }
194        entry_dict->SetIntegerWithoutPathExpansion(
195            chromeos::kAccountsPrefDeviceLocalAccountsKeyType, entry->type());
196        if (entry->kiosk_app().has_app_id()) {
197          entry_dict->SetStringWithoutPathExpansion(
198              chromeos::kAccountsPrefDeviceLocalAccountsKeyKioskAppId,
199              entry->kiosk_app().app_id());
200        }
201      } else if (entry->has_deprecated_public_session_id()) {
202        // Deprecated public session specification.
203        entry_dict->SetStringWithoutPathExpansion(
204            chromeos::kAccountsPrefDeviceLocalAccountsKeyId,
205            entry->deprecated_public_session_id());
206        entry_dict->SetIntegerWithoutPathExpansion(
207            chromeos::kAccountsPrefDeviceLocalAccountsKeyType,
208            DeviceLocalAccount::TYPE_PUBLIC_SESSION);
209      }
210      account_list->Append(entry_dict.release());
211    }
212    policies->Set(key::kDeviceLocalAccounts,
213                  POLICY_LEVEL_MANDATORY,
214                  POLICY_SCOPE_MACHINE,
215                  account_list.release(),
216                  NULL);
217    if (container.has_auto_login_id()) {
218      policies->Set(key::kDeviceLocalAccountAutoLoginId,
219                    POLICY_LEVEL_MANDATORY,
220                    POLICY_SCOPE_MACHINE,
221                    new base::StringValue(container.auto_login_id()),
222                    NULL);
223    }
224    if (container.has_auto_login_delay()) {
225      policies->Set(key::kDeviceLocalAccountAutoLoginDelay,
226                    POLICY_LEVEL_MANDATORY,
227                    POLICY_SCOPE_MACHINE,
228                    DecodeIntegerValue(container.auto_login_delay()).release(),
229                    NULL);
230    }
231    if (container.has_enable_auto_login_bailout()) {
232      policies->Set(key::kDeviceLocalAccountAutoLoginBailoutEnabled,
233                    POLICY_LEVEL_MANDATORY,
234                    POLICY_SCOPE_MACHINE,
235                    new base::FundamentalValue(
236                        container.enable_auto_login_bailout()),
237                    NULL);
238    }
239    if (container.has_prompt_for_network_when_offline()) {
240      policies->Set(key::kDeviceLocalAccountPromptForNetworkWhenOffline,
241                    POLICY_LEVEL_MANDATORY,
242                    POLICY_SCOPE_MACHINE,
243                    new base::FundamentalValue(
244                        container.prompt_for_network_when_offline()),
245                    NULL);
246    }
247  }
248
249  if (policy.has_supervised_users_settings()) {
250    const em::SupervisedUsersSettingsProto& container =
251        policy.supervised_users_settings();
252    if (container.has_supervised_users_enabled()) {
253      base::Value* value = new base::FundamentalValue(
254          container.supervised_users_enabled());
255      policies->Set(key::kSupervisedUsersEnabled,
256                    POLICY_LEVEL_MANDATORY,
257                    POLICY_SCOPE_MACHINE,
258                    value,
259                    NULL);
260    }
261  }
262}
263
264void DecodeKioskPolicies(const em::ChromeDeviceSettingsProto& policy,
265                         PolicyMap* policies,
266                         EnterpriseInstallAttributes* install_attributes) {
267  // No policies if this is not KIOSK.
268  if (install_attributes->GetMode() != DEVICE_MODE_RETAIL_KIOSK)
269    return;
270
271  if (policy.has_forced_logout_timeouts()) {
272    const em::ForcedLogoutTimeoutsProto& container(
273        policy.forced_logout_timeouts());
274    if (container.has_idle_logout_timeout()) {
275      policies->Set(
276          key::kDeviceIdleLogoutTimeout,
277          POLICY_LEVEL_MANDATORY,
278          POLICY_SCOPE_MACHINE,
279          DecodeIntegerValue(container.idle_logout_timeout()).release(),
280          NULL);
281    }
282    if (container.has_idle_logout_warning_duration()) {
283      policies->Set(key::kDeviceIdleLogoutWarningDuration,
284                    POLICY_LEVEL_MANDATORY,
285                    POLICY_SCOPE_MACHINE,
286                    DecodeIntegerValue(container.idle_logout_warning_duration())
287                        .release(),
288                    NULL);
289    }
290  }
291
292  if (policy.has_login_screen_saver()) {
293    const em::ScreenSaverProto& container(
294        policy.login_screen_saver());
295    if (container.has_screen_saver_extension_id()) {
296      policies->Set(key::kDeviceLoginScreenSaverId,
297                    POLICY_LEVEL_MANDATORY,
298                    POLICY_SCOPE_MACHINE,
299                    new base::StringValue(
300                        container.screen_saver_extension_id()),
301                    NULL);
302    }
303    if (container.has_screen_saver_timeout()) {
304      policies->Set(
305          key::kDeviceLoginScreenSaverTimeout,
306          POLICY_LEVEL_MANDATORY,
307          POLICY_SCOPE_MACHINE,
308          DecodeIntegerValue(container.screen_saver_timeout()).release(),
309          NULL);
310    }
311  }
312
313  if (policy.has_app_pack()) {
314    const em::AppPackProto& container(policy.app_pack());
315    base::ListValue* app_pack_list = new base::ListValue();
316    for (int i = 0; i < container.app_pack_size(); ++i) {
317      const em::AppPackEntryProto& entry(container.app_pack(i));
318      if (entry.has_extension_id() && entry.has_update_url()) {
319        base::DictionaryValue* dict = new base::DictionaryValue();
320        dict->SetString(chromeos::kAppPackKeyExtensionId, entry.extension_id());
321        dict->SetString(chromeos::kAppPackKeyUpdateUrl, entry.update_url());
322        app_pack_list->Append(dict);
323      }
324    }
325    policies->Set(key::kDeviceAppPack,
326                  POLICY_LEVEL_MANDATORY,
327                  POLICY_SCOPE_MACHINE,
328                  app_pack_list,
329                  NULL);
330  }
331
332  if (policy.has_pinned_apps()) {
333    const em::PinnedAppsProto& container(policy.pinned_apps());
334    base::ListValue* pinned_apps_list = new base::ListValue();
335    for (int i = 0; i < container.app_id_size(); ++i) {
336      pinned_apps_list->Append(
337          new base::StringValue(container.app_id(i)));
338    }
339
340    policies->Set(key::kPinnedLauncherApps,
341                  POLICY_LEVEL_RECOMMENDED,
342                  POLICY_SCOPE_MACHINE,
343                  pinned_apps_list,
344                  NULL);
345  }
346}
347
348void DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto& policy,
349                           PolicyMap* policies,
350                           EnterpriseInstallAttributes* install_attributes) {
351  if (policy.has_device_proxy_settings()) {
352    const em::DeviceProxySettingsProto& container(
353        policy.device_proxy_settings());
354    scoped_ptr<base::DictionaryValue> proxy_settings(new base::DictionaryValue);
355    if (container.has_proxy_mode())
356      proxy_settings->SetString(key::kProxyMode, container.proxy_mode());
357    if (container.has_proxy_server())
358      proxy_settings->SetString(key::kProxyServer, container.proxy_server());
359    if (container.has_proxy_pac_url())
360      proxy_settings->SetString(key::kProxyPacUrl, container.proxy_pac_url());
361    if (container.has_proxy_bypass_list()) {
362      proxy_settings->SetString(key::kProxyBypassList,
363                                container.proxy_bypass_list());
364    }
365
366    // Figure out the level. Proxy policy is mandatory in kiosk mode.
367    PolicyLevel level = POLICY_LEVEL_RECOMMENDED;
368    if (install_attributes->GetMode() == DEVICE_MODE_RETAIL_KIOSK)
369      level = POLICY_LEVEL_MANDATORY;
370
371    if (!proxy_settings->empty()) {
372      policies->Set(key::kProxySettings,
373                    level,
374                    POLICY_SCOPE_MACHINE,
375                    proxy_settings.release(),
376                    NULL);
377    }
378  }
379
380  if (policy.has_data_roaming_enabled()) {
381    const em::DataRoamingEnabledProto& container(policy.data_roaming_enabled());
382    if (container.has_data_roaming_enabled()) {
383      policies->Set(key::kDeviceDataRoamingEnabled,
384                    POLICY_LEVEL_MANDATORY,
385                    POLICY_SCOPE_MACHINE,
386                    new base::FundamentalValue(
387                        container.data_roaming_enabled()),
388                    NULL);
389    }
390  }
391
392  if (policy.has_open_network_configuration() &&
393      policy.open_network_configuration().has_open_network_configuration()) {
394    std::string config(
395        policy.open_network_configuration().open_network_configuration());
396    policies->Set(key::kDeviceOpenNetworkConfiguration,
397                  POLICY_LEVEL_MANDATORY,
398                  POLICY_SCOPE_MACHINE,
399                  new base::StringValue(config),
400                  NULL);
401  }
402}
403
404void DecodeReportingPolicies(const em::ChromeDeviceSettingsProto& policy,
405                             PolicyMap* policies) {
406  if (policy.has_device_reporting()) {
407    const em::DeviceReportingProto& container(policy.device_reporting());
408    if (container.has_report_version_info()) {
409      policies->Set(key::kReportDeviceVersionInfo,
410                    POLICY_LEVEL_MANDATORY,
411                    POLICY_SCOPE_MACHINE,
412                    new base::FundamentalValue(
413                        container.report_version_info()),
414                    NULL);
415    }
416    if (container.has_report_activity_times()) {
417      policies->Set(key::kReportDeviceActivityTimes,
418                    POLICY_LEVEL_MANDATORY,
419                    POLICY_SCOPE_MACHINE,
420                    new base::FundamentalValue(
421                        container.report_activity_times()),
422                    NULL);
423    }
424    if (container.has_report_boot_mode()) {
425      policies->Set(key::kReportDeviceBootMode,
426                    POLICY_LEVEL_MANDATORY,
427                    POLICY_SCOPE_MACHINE,
428                    new base::FundamentalValue(
429                        container.report_boot_mode()),
430                    NULL);
431    }
432    if (container.has_report_location()) {
433      policies->Set(key::kReportDeviceLocation,
434                    POLICY_LEVEL_MANDATORY,
435                    POLICY_SCOPE_MACHINE,
436                    new base::FundamentalValue(
437                        container.report_location()),
438                    NULL);
439    }
440    if (container.has_report_network_interfaces()) {
441      policies->Set(key::kReportDeviceNetworkInterfaces,
442                    POLICY_LEVEL_MANDATORY,
443                    POLICY_SCOPE_MACHINE,
444                    new base::FundamentalValue(
445                        container.report_network_interfaces()),
446                    NULL);
447    }
448    if (container.has_report_users()) {
449      policies->Set(key::kReportDeviceUsers,
450                    POLICY_LEVEL_MANDATORY,
451                    POLICY_SCOPE_MACHINE,
452                    new base::FundamentalValue(container.report_users()),
453                    NULL);
454    }
455  }
456}
457
458void DecodeAutoUpdatePolicies(const em::ChromeDeviceSettingsProto& policy,
459                              PolicyMap* policies) {
460  if (policy.has_release_channel()) {
461    const em::ReleaseChannelProto& container(policy.release_channel());
462    if (container.has_release_channel()) {
463      std::string channel(container.release_channel());
464      policies->Set(key::kChromeOsReleaseChannel,
465                    POLICY_LEVEL_MANDATORY,
466                    POLICY_SCOPE_MACHINE,
467                    new base::StringValue(channel),
468                    NULL);
469      // TODO(dubroy): Once http://crosbug.com/17015 is implemented, we won't
470      // have to pass the channel in here, only ping the update engine to tell
471      // it to fetch the channel from the policy.
472      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
473          SetChannel(channel, false);
474    }
475    if (container.has_release_channel_delegated()) {
476      policies->Set(key::kChromeOsReleaseChannelDelegated,
477                    POLICY_LEVEL_MANDATORY,
478                    POLICY_SCOPE_MACHINE,
479                    new base::FundamentalValue(
480                        container.release_channel_delegated()),
481                    NULL);
482    }
483  }
484
485  if (policy.has_auto_update_settings()) {
486    const em::AutoUpdateSettingsProto& container(policy.auto_update_settings());
487    if (container.has_update_disabled()) {
488      policies->Set(key::kDeviceAutoUpdateDisabled,
489                    POLICY_LEVEL_MANDATORY,
490                    POLICY_SCOPE_MACHINE,
491                    new base::FundamentalValue(
492                        container.update_disabled()),
493                    NULL);
494    }
495
496    if (container.has_target_version_prefix()) {
497      policies->Set(key::kDeviceTargetVersionPrefix,
498                    POLICY_LEVEL_MANDATORY,
499                    POLICY_SCOPE_MACHINE,
500                    new base::StringValue(
501                        container.target_version_prefix()),
502                    NULL);
503    }
504
505    // target_version_display_name is not actually a policy, but a display
506    // string for target_version_prefix, so we ignore it.
507
508    if (container.has_scatter_factor_in_seconds()) {
509      policies->Set(key::kDeviceUpdateScatterFactor,
510                    POLICY_LEVEL_MANDATORY,
511                    POLICY_SCOPE_MACHINE,
512                    new base::FundamentalValue(static_cast<int>(
513                        container.scatter_factor_in_seconds())),
514                    NULL);
515    }
516
517    if (container.allowed_connection_types_size()) {
518      base::ListValue* allowed_connection_types = new base::ListValue();
519      RepeatedField<int>::const_iterator entry;
520      for (entry = container.allowed_connection_types().begin();
521           entry != container.allowed_connection_types().end();
522           ++entry) {
523        base::Value* value = DecodeConnectionType(*entry);
524        if (value)
525          allowed_connection_types->Append(value);
526      }
527      policies->Set(key::kDeviceUpdateAllowedConnectionTypes,
528                    POLICY_LEVEL_MANDATORY,
529                    POLICY_SCOPE_MACHINE,
530                    allowed_connection_types,
531                    NULL);
532    }
533
534    if (container.has_http_downloads_enabled()) {
535      policies->Set(
536          key::kDeviceUpdateHttpDownloadsEnabled,
537          POLICY_LEVEL_MANDATORY,
538          POLICY_SCOPE_MACHINE,
539          new base::FundamentalValue(container.http_downloads_enabled()),
540          NULL);
541    }
542
543    if (container.has_reboot_after_update()) {
544      policies->Set(key::kRebootAfterUpdate,
545                    POLICY_LEVEL_MANDATORY,
546                    POLICY_SCOPE_MACHINE,
547                    new base::FundamentalValue(
548                        container.reboot_after_update()),
549                    NULL);
550    }
551
552    if (container.has_p2p_enabled()) {
553      policies->Set(key::kDeviceAutoUpdateP2PEnabled,
554                    POLICY_LEVEL_MANDATORY,
555                    POLICY_SCOPE_MACHINE,
556                    new base::FundamentalValue(container.p2p_enabled()),
557                    NULL);
558    }
559  }
560}
561
562void DecodeAccessibilityPolicies(const em::ChromeDeviceSettingsProto& policy,
563                                 PolicyMap* policies) {
564  if (policy.has_accessibility_settings()) {
565    const em::AccessibilitySettingsProto&
566        container(policy.accessibility_settings());
567
568    if (container.has_login_screen_default_large_cursor_enabled()) {
569      policies->Set(
570          key::kDeviceLoginScreenDefaultLargeCursorEnabled,
571          POLICY_LEVEL_MANDATORY,
572          POLICY_SCOPE_MACHINE,
573          new base::FundamentalValue(
574              container.login_screen_default_large_cursor_enabled()),
575          NULL);
576    }
577
578    if (container.has_login_screen_default_spoken_feedback_enabled()) {
579      policies->Set(
580          key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
581          POLICY_LEVEL_MANDATORY,
582          POLICY_SCOPE_MACHINE,
583          new base::FundamentalValue(
584              container.login_screen_default_spoken_feedback_enabled()),
585          NULL);
586    }
587
588    if (container.has_login_screen_default_high_contrast_enabled()) {
589      policies->Set(
590          key::kDeviceLoginScreenDefaultHighContrastEnabled,
591          POLICY_LEVEL_MANDATORY,
592          POLICY_SCOPE_MACHINE,
593          new base::FundamentalValue(
594              container.login_screen_default_high_contrast_enabled()),
595          NULL);
596    }
597
598    if (container.has_login_screen_default_screen_magnifier_type()) {
599      policies->Set(
600          key::kDeviceLoginScreenDefaultScreenMagnifierType,
601          POLICY_LEVEL_MANDATORY,
602          POLICY_SCOPE_MACHINE,
603          DecodeIntegerValue(
604              container.login_screen_default_screen_magnifier_type()).release(),
605          NULL);
606    }
607    if (container.has_login_screen_default_virtual_keyboard_enabled()) {
608      policies->Set(
609          key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled,
610          POLICY_LEVEL_MANDATORY,
611          POLICY_SCOPE_MACHINE,
612          new base::FundamentalValue(
613              container.login_screen_default_virtual_keyboard_enabled()),
614          NULL);
615    }
616  }
617}
618
619void DecodeGenericPolicies(const em::ChromeDeviceSettingsProto& policy,
620                           PolicyMap* policies) {
621  if (policy.has_device_policy_refresh_rate()) {
622    const em::DevicePolicyRefreshRateProto& container(
623        policy.device_policy_refresh_rate());
624    if (container.has_device_policy_refresh_rate()) {
625      policies->Set(
626          key::kDevicePolicyRefreshRate,
627          POLICY_LEVEL_MANDATORY,
628          POLICY_SCOPE_MACHINE,
629          DecodeIntegerValue(container.device_policy_refresh_rate()).release(),
630          NULL);
631    }
632  }
633
634  if (policy.has_metrics_enabled()) {
635    const em::MetricsEnabledProto& container(policy.metrics_enabled());
636    if (container.has_metrics_enabled()) {
637      policies->Set(key::kDeviceMetricsReportingEnabled,
638                    POLICY_LEVEL_MANDATORY,
639                    POLICY_SCOPE_MACHINE,
640                    new base::FundamentalValue(
641                        container.metrics_enabled()),
642                    NULL);
643    }
644  }
645
646  if (policy.has_start_up_urls()) {
647    const em::StartUpUrlsProto& container(policy.start_up_urls());
648    base::ListValue* urls = new base::ListValue();
649    RepeatedPtrField<std::string>::const_iterator entry;
650    for (entry = container.start_up_urls().begin();
651         entry != container.start_up_urls().end();
652         ++entry) {
653      urls->Append(new base::StringValue(*entry));
654    }
655    policies->Set(key::kDeviceStartUpUrls,
656                  POLICY_LEVEL_MANDATORY,
657                  POLICY_SCOPE_MACHINE,
658                  urls,
659                  NULL);
660  }
661
662  if (policy.has_system_timezone()) {
663    if (policy.system_timezone().has_timezone()) {
664      policies->Set(key::kSystemTimezone,
665                    POLICY_LEVEL_MANDATORY,
666                    POLICY_SCOPE_MACHINE,
667                    new base::StringValue(
668                        policy.system_timezone().timezone()),
669                    NULL);
670    }
671  }
672
673  if (policy.has_use_24hour_clock()) {
674    if (policy.use_24hour_clock().has_use_24hour_clock()) {
675      policies->Set(key::kSystemUse24HourClock,
676                    POLICY_LEVEL_MANDATORY,
677                    POLICY_SCOPE_MACHINE,
678                    new base::FundamentalValue(
679                        policy.use_24hour_clock().use_24hour_clock()),
680                    NULL);
681    }
682  }
683
684  if (policy.has_allow_redeem_offers()) {
685    const em::AllowRedeemChromeOsRegistrationOffersProto& container(
686        policy.allow_redeem_offers());
687    if (container.has_allow_redeem_offers()) {
688      policies->Set(key::kDeviceAllowRedeemChromeOsRegistrationOffers,
689                    POLICY_LEVEL_MANDATORY,
690                    POLICY_SCOPE_MACHINE,
691                    new base::FundamentalValue(
692                        container.allow_redeem_offers()),
693                    NULL);
694    }
695  }
696
697  if (policy.has_uptime_limit()) {
698    const em::UptimeLimitProto& container(policy.uptime_limit());
699    if (container.has_uptime_limit()) {
700      policies->Set(key::kUptimeLimit,
701                    POLICY_LEVEL_MANDATORY,
702                    POLICY_SCOPE_MACHINE,
703                    DecodeIntegerValue(container.uptime_limit()).release(),
704                    NULL);
705    }
706  }
707
708  if (policy.has_start_up_flags()) {
709    const em::StartUpFlagsProto& container(policy.start_up_flags());
710    base::ListValue* flags = new base::ListValue();
711    RepeatedPtrField<std::string>::const_iterator entry;
712    for (entry = container.flags().begin();
713         entry != container.flags().end();
714         ++entry) {
715      flags->Append(new base::StringValue(*entry));
716    }
717    policies->Set(key::kDeviceStartUpFlags,
718                  POLICY_LEVEL_MANDATORY,
719                  POLICY_SCOPE_MACHINE,
720                  flags,
721                  NULL);
722  }
723
724  if (policy.has_variations_parameter()) {
725    if (policy.variations_parameter().has_parameter()) {
726      policies->Set(key::kDeviceVariationsRestrictParameter,
727                    POLICY_LEVEL_MANDATORY,
728                    POLICY_SCOPE_MACHINE,
729                    new base::StringValue(
730                        policy.variations_parameter().parameter()),
731                    NULL);
732    }
733  }
734
735  if (policy.has_attestation_settings()) {
736    if (policy.attestation_settings().has_attestation_enabled()) {
737      policies->Set(key::kAttestationEnabledForDevice,
738                    POLICY_LEVEL_MANDATORY,
739                    POLICY_SCOPE_MACHINE,
740                    new base::FundamentalValue(
741                        policy.attestation_settings().attestation_enabled()),
742                    NULL);
743    }
744    if (policy.attestation_settings().has_content_protection_enabled()) {
745      policies->Set(
746          key::kAttestationForContentProtectionEnabled,
747          POLICY_LEVEL_MANDATORY,
748          POLICY_SCOPE_MACHINE,
749          new base::FundamentalValue(
750              policy.attestation_settings().content_protection_enabled()),
751          NULL);
752    }
753  }
754
755  if (policy.has_login_screen_power_management()) {
756    const em::LoginScreenPowerManagementProto& container(
757        policy.login_screen_power_management());
758    if (container.has_login_screen_power_management()) {
759      scoped_ptr<base::Value> decoded_json;
760      decoded_json = DecodeJsonStringAndDropUnknownBySchema(
761          container.login_screen_power_management(),
762          key::kDeviceLoginScreenPowerManagement);
763      if (decoded_json) {
764        policies->Set(key::kDeviceLoginScreenPowerManagement,
765                      POLICY_LEVEL_MANDATORY,
766                      POLICY_SCOPE_MACHINE,
767                      decoded_json.release(),
768                      NULL);
769      }
770    }
771  }
772
773  if (policy.has_system_settings()) {
774    const em::SystemSettingsProto& container(policy.system_settings());
775    if (container.has_block_devmode()) {
776      policies->Set(
777          key::kDeviceBlockDevmode,
778          POLICY_LEVEL_MANDATORY,
779          POLICY_SCOPE_MACHINE,
780          new base::FundamentalValue(container.block_devmode()),
781          NULL);
782    }
783  }
784}
785
786}  // namespace
787
788void DecodeDevicePolicy(const em::ChromeDeviceSettingsProto& policy,
789                        PolicyMap* policies,
790                        EnterpriseInstallAttributes* install_attributes) {
791  // TODO(achuith): Remove this once crbug.com/263527 is resolved.
792  VLOG(2) << "DecodeDevicePolicy " << policy.SerializeAsString();
793
794  // Decode the various groups of policies.
795  DecodeLoginPolicies(policy, policies);
796  DecodeKioskPolicies(policy, policies, install_attributes);
797  DecodeNetworkPolicies(policy, policies, install_attributes);
798  DecodeReportingPolicies(policy, policies);
799  DecodeAutoUpdatePolicies(policy, policies);
800  DecodeAccessibilityPolicies(policy, policies);
801  DecodeGenericPolicies(policy, policies);
802}
803
804}  // namespace policy
805