| OLD | NEW |
| (Empty) |
| 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/policy/device_policy_decoder_chromeos.h" | |
| 6 | |
| 7 #include <limits> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "base/values.h" | |
| 11 #include "chrome/browser/chromeos/settings/cros_settings_names.h" | |
| 12 #include "chrome/browser/policy/app_pack_updater.h" | |
| 13 #include "chrome/browser/policy/enterprise_install_attributes.h" | |
| 14 #include "chrome/browser/policy/policy_map.h" | |
| 15 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h" | |
| 16 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 17 #include "chromeos/dbus/update_engine_client.h" | |
| 18 #include "policy/policy_constants.h" | |
| 19 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 20 | |
| 21 using google::protobuf::RepeatedField; | |
| 22 using google::protobuf::RepeatedPtrField; | |
| 23 | |
| 24 namespace em = enterprise_management; | |
| 25 | |
| 26 namespace policy { | |
| 27 | |
| 28 namespace { | |
| 29 | |
| 30 // Decodes a protobuf integer to an IntegerValue. The caller assumes ownership | |
| 31 // of the return Value*. Returns NULL in case the input value is out of bounds. | |
| 32 Value* DecodeIntegerValue(google::protobuf::int64 value) { | |
| 33 if (value < std::numeric_limits<int>::min() || | |
| 34 value > std::numeric_limits<int>::max()) { | |
| 35 LOG(WARNING) << "Integer value " << value | |
| 36 << " out of numeric limits, ignoring."; | |
| 37 return NULL; | |
| 38 } | |
| 39 | |
| 40 return Value::CreateIntegerValue(static_cast<int>(value)); | |
| 41 } | |
| 42 | |
| 43 Value* DecodeConnectionType(int value) { | |
| 44 static const char* const kConnectionTypes[] = { | |
| 45 flimflam::kTypeEthernet, | |
| 46 flimflam::kTypeWifi, | |
| 47 flimflam::kTypeWimax, | |
| 48 flimflam::kTypeBluetooth, | |
| 49 flimflam::kTypeCellular, | |
| 50 }; | |
| 51 | |
| 52 if (value < 0 || value >= static_cast<int>(arraysize(kConnectionTypes))) | |
| 53 return NULL; | |
| 54 | |
| 55 return Value::CreateStringValue(kConnectionTypes[value]); | |
| 56 } | |
| 57 | |
| 58 void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy, | |
| 59 PolicyMap* policies) { | |
| 60 if (policy.has_guest_mode_enabled()) { | |
| 61 const em::GuestModeEnabledProto& container(policy.guest_mode_enabled()); | |
| 62 if (container.has_guest_mode_enabled()) { | |
| 63 policies->Set(key::kDeviceGuestModeEnabled, | |
| 64 POLICY_LEVEL_MANDATORY, | |
| 65 POLICY_SCOPE_MACHINE, | |
| 66 Value::CreateBooleanValue(container.guest_mode_enabled())); | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 if (policy.has_show_user_names()) { | |
| 71 const em::ShowUserNamesOnSigninProto& container(policy.show_user_names()); | |
| 72 if (container.has_show_user_names()) { | |
| 73 policies->Set(key::kDeviceShowUserNamesOnSignin, | |
| 74 POLICY_LEVEL_MANDATORY, | |
| 75 POLICY_SCOPE_MACHINE, | |
| 76 Value::CreateBooleanValue(container.show_user_names())); | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 if (policy.has_allow_new_users()) { | |
| 81 const em::AllowNewUsersProto& container(policy.allow_new_users()); | |
| 82 if (container.has_allow_new_users()) { | |
| 83 policies->Set(key::kDeviceAllowNewUsers, | |
| 84 POLICY_LEVEL_MANDATORY, | |
| 85 POLICY_SCOPE_MACHINE, | |
| 86 Value::CreateBooleanValue(container.allow_new_users())); | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 if (policy.has_user_whitelist()) { | |
| 91 const em::UserWhitelistProto& container(policy.user_whitelist()); | |
| 92 if (container.user_whitelist_size()) { | |
| 93 ListValue* whitelist = new ListValue(); | |
| 94 RepeatedPtrField<std::string>::const_iterator entry; | |
| 95 for (entry = container.user_whitelist().begin(); | |
| 96 entry != container.user_whitelist().end(); | |
| 97 ++entry) { | |
| 98 whitelist->Append(Value::CreateStringValue(*entry)); | |
| 99 } | |
| 100 policies->Set(key::kDeviceUserWhitelist, | |
| 101 POLICY_LEVEL_MANDATORY, | |
| 102 POLICY_SCOPE_MACHINE, | |
| 103 whitelist); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 if (policy.has_ephemeral_users_enabled()) { | |
| 108 const em::EphemeralUsersEnabledProto& container( | |
| 109 policy.ephemeral_users_enabled()); | |
| 110 if (container.has_ephemeral_users_enabled()) { | |
| 111 policies->Set(key::kDeviceEphemeralUsersEnabled, | |
| 112 POLICY_LEVEL_MANDATORY, | |
| 113 POLICY_SCOPE_MACHINE, | |
| 114 Value::CreateBooleanValue( | |
| 115 container.ephemeral_users_enabled())); | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 if (policy.has_device_local_accounts()) { | |
| 120 const RepeatedPtrField<em::DeviceLocalAccountInfoProto>& accounts = | |
| 121 policy.device_local_accounts().account(); | |
| 122 if (accounts.size() > 0) { | |
| 123 ListValue* account_list = new ListValue(); | |
| 124 RepeatedPtrField<em::DeviceLocalAccountInfoProto>::const_iterator entry; | |
| 125 for (entry = accounts.begin(); entry != accounts.end(); ++entry) { | |
| 126 if (entry->has_id()) | |
| 127 account_list->AppendString(entry->id()); | |
| 128 } | |
| 129 policies->Set(key::kDeviceLocalAccounts, | |
| 130 POLICY_LEVEL_MANDATORY, | |
| 131 POLICY_SCOPE_MACHINE, | |
| 132 account_list); | |
| 133 } | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 void DecodeKioskPolicies(const em::ChromeDeviceSettingsProto& policy, | |
| 138 PolicyMap* policies, | |
| 139 EnterpriseInstallAttributes* install_attributes) { | |
| 140 // No policies if this is not KIOSK. | |
| 141 if (install_attributes->GetMode() != DEVICE_MODE_KIOSK) | |
| 142 return; | |
| 143 | |
| 144 if (policy.has_forced_logout_timeouts()) { | |
| 145 const em::ForcedLogoutTimeoutsProto& container( | |
| 146 policy.forced_logout_timeouts()); | |
| 147 if (container.has_idle_logout_timeout()) { | |
| 148 policies->Set(key::kDeviceIdleLogoutTimeout, | |
| 149 POLICY_LEVEL_MANDATORY, | |
| 150 POLICY_SCOPE_MACHINE, | |
| 151 DecodeIntegerValue(container.idle_logout_timeout())); | |
| 152 } | |
| 153 if (container.has_idle_logout_warning_duration()) { | |
| 154 policies->Set(key::kDeviceIdleLogoutWarningDuration, | |
| 155 POLICY_LEVEL_MANDATORY, | |
| 156 POLICY_SCOPE_MACHINE, | |
| 157 DecodeIntegerValue( | |
| 158 container.idle_logout_warning_duration())); | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 if (policy.has_login_screen_saver()) { | |
| 163 const em::ScreenSaverProto& container( | |
| 164 policy.login_screen_saver()); | |
| 165 if (container.has_screen_saver_extension_id()) { | |
| 166 policies->Set(key::kDeviceLoginScreenSaverId, | |
| 167 POLICY_LEVEL_MANDATORY, | |
| 168 POLICY_SCOPE_MACHINE, | |
| 169 Value::CreateStringValue( | |
| 170 container.screen_saver_extension_id())); | |
| 171 } | |
| 172 if (container.has_screen_saver_timeout()) { | |
| 173 policies->Set(key::kDeviceLoginScreenSaverTimeout, | |
| 174 POLICY_LEVEL_MANDATORY, | |
| 175 POLICY_SCOPE_MACHINE, | |
| 176 DecodeIntegerValue(container.screen_saver_timeout())); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 if (policy.has_app_pack()) { | |
| 181 const em::AppPackProto& container(policy.app_pack()); | |
| 182 base::ListValue* app_pack_list = new base::ListValue(); | |
| 183 for (int i = 0; i < container.app_pack_size(); ++i) { | |
| 184 const em::AppPackEntryProto& entry(container.app_pack(i)); | |
| 185 if (entry.has_extension_id() && entry.has_update_url()) { | |
| 186 base::DictionaryValue* dict = new base::DictionaryValue(); | |
| 187 dict->SetString(AppPackUpdater::kExtensionId, entry.extension_id()); | |
| 188 dict->SetString(AppPackUpdater::kUpdateUrl, entry.update_url()); | |
| 189 app_pack_list->Append(dict); | |
| 190 } | |
| 191 } | |
| 192 policies->Set(key::kDeviceAppPack, | |
| 193 POLICY_LEVEL_MANDATORY, | |
| 194 POLICY_SCOPE_MACHINE, | |
| 195 app_pack_list); | |
| 196 } | |
| 197 | |
| 198 if (policy.has_pinned_apps()) { | |
| 199 const em::PinnedAppsProto& container(policy.pinned_apps()); | |
| 200 base::ListValue* pinned_apps_list = new base::ListValue(); | |
| 201 for (int i = 0; i < container.app_id_size(); ++i) | |
| 202 pinned_apps_list->Append(Value::CreateStringValue(container.app_id(i))); | |
| 203 | |
| 204 policies->Set(key::kPinnedLauncherApps, | |
| 205 POLICY_LEVEL_RECOMMENDED, | |
| 206 POLICY_SCOPE_MACHINE, | |
| 207 pinned_apps_list); | |
| 208 } | |
| 209 } | |
| 210 | |
| 211 void DecodeNetworkPolicies(const em::ChromeDeviceSettingsProto& policy, | |
| 212 PolicyMap* policies, | |
| 213 EnterpriseInstallAttributes* install_attributes) { | |
| 214 if (policy.has_device_proxy_settings()) { | |
| 215 const em::DeviceProxySettingsProto& container( | |
| 216 policy.device_proxy_settings()); | |
| 217 scoped_ptr<DictionaryValue> proxy_settings(new DictionaryValue); | |
| 218 if (container.has_proxy_mode()) | |
| 219 proxy_settings->SetString(key::kProxyMode, container.proxy_mode()); | |
| 220 if (container.has_proxy_server()) | |
| 221 proxy_settings->SetString(key::kProxyServer, container.proxy_server()); | |
| 222 if (container.has_proxy_pac_url()) | |
| 223 proxy_settings->SetString(key::kProxyPacUrl, container.proxy_pac_url()); | |
| 224 if (container.has_proxy_bypass_list()) { | |
| 225 proxy_settings->SetString(key::kProxyBypassList, | |
| 226 container.proxy_bypass_list()); | |
| 227 } | |
| 228 | |
| 229 // Figure out the level. Proxy policy is mandatory in kiosk mode. | |
| 230 PolicyLevel level = POLICY_LEVEL_RECOMMENDED; | |
| 231 if (install_attributes->GetMode() == DEVICE_MODE_KIOSK) | |
| 232 level = POLICY_LEVEL_MANDATORY; | |
| 233 | |
| 234 if (!proxy_settings->empty()) { | |
| 235 policies->Set(key::kProxySettings, | |
| 236 level, | |
| 237 POLICY_SCOPE_MACHINE, | |
| 238 proxy_settings.release()); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 if (policy.has_data_roaming_enabled()) { | |
| 243 const em::DataRoamingEnabledProto& container(policy.data_roaming_enabled()); | |
| 244 if (container.has_data_roaming_enabled()) { | |
| 245 policies->Set(key::kDeviceDataRoamingEnabled, | |
| 246 POLICY_LEVEL_MANDATORY, | |
| 247 POLICY_SCOPE_MACHINE, | |
| 248 Value::CreateBooleanValue( | |
| 249 container.data_roaming_enabled())); | |
| 250 } | |
| 251 } | |
| 252 | |
| 253 if (policy.has_open_network_configuration() && | |
| 254 policy.open_network_configuration().has_open_network_configuration()) { | |
| 255 std::string config( | |
| 256 policy.open_network_configuration().open_network_configuration()); | |
| 257 policies->Set(key::kDeviceOpenNetworkConfiguration, | |
| 258 POLICY_LEVEL_MANDATORY, | |
| 259 POLICY_SCOPE_MACHINE, | |
| 260 Value::CreateStringValue(config)); | |
| 261 } | |
| 262 } | |
| 263 | |
| 264 void DecodeReportingPolicies(const em::ChromeDeviceSettingsProto& policy, | |
| 265 PolicyMap* policies) { | |
| 266 if (policy.has_device_reporting()) { | |
| 267 const em::DeviceReportingProto& container(policy.device_reporting()); | |
| 268 if (container.has_report_version_info()) { | |
| 269 policies->Set(key::kReportDeviceVersionInfo, | |
| 270 POLICY_LEVEL_MANDATORY, | |
| 271 POLICY_SCOPE_MACHINE, | |
| 272 Value::CreateBooleanValue(container.report_version_info())); | |
| 273 } | |
| 274 if (container.has_report_activity_times()) { | |
| 275 policies->Set(key::kReportDeviceActivityTimes, | |
| 276 POLICY_LEVEL_MANDATORY, | |
| 277 POLICY_SCOPE_MACHINE, | |
| 278 Value::CreateBooleanValue( | |
| 279 container.report_activity_times())); | |
| 280 } | |
| 281 if (container.has_report_boot_mode()) { | |
| 282 policies->Set(key::kReportDeviceBootMode, | |
| 283 POLICY_LEVEL_MANDATORY, | |
| 284 POLICY_SCOPE_MACHINE, | |
| 285 Value::CreateBooleanValue(container.report_boot_mode())); | |
| 286 } | |
| 287 if (container.has_report_location()) { | |
| 288 policies->Set(key::kReportDeviceLocation, | |
| 289 POLICY_LEVEL_MANDATORY, | |
| 290 POLICY_SCOPE_MACHINE, | |
| 291 Value::CreateBooleanValue(container.report_location())); | |
| 292 } | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 void DecodeAutoUpdatePolicies(const em::ChromeDeviceSettingsProto& policy, | |
| 297 PolicyMap* policies) { | |
| 298 if (policy.has_release_channel()) { | |
| 299 const em::ReleaseChannelProto& container(policy.release_channel()); | |
| 300 if (container.has_release_channel()) { | |
| 301 std::string channel(container.release_channel()); | |
| 302 policies->Set(key::kChromeOsReleaseChannel, | |
| 303 POLICY_LEVEL_MANDATORY, | |
| 304 POLICY_SCOPE_MACHINE, | |
| 305 Value::CreateStringValue(channel)); | |
| 306 // TODO(dubroy): Once http://crosbug.com/17015 is implemented, we won't | |
| 307 // have to pass the channel in here, only ping the update engine to tell | |
| 308 // it to fetch the channel from the policy. | |
| 309 chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()-> | |
| 310 SetReleaseTrack(channel); | |
| 311 } | |
| 312 if (container.has_release_channel_delegated()) { | |
| 313 policies->Set(key::kChromeOsReleaseChannelDelegated, | |
| 314 POLICY_LEVEL_MANDATORY, | |
| 315 POLICY_SCOPE_MACHINE, | |
| 316 Value::CreateBooleanValue( | |
| 317 container.release_channel_delegated())); | |
| 318 } | |
| 319 } | |
| 320 | |
| 321 if (policy.has_auto_update_settings()) { | |
| 322 const em::AutoUpdateSettingsProto& container(policy.auto_update_settings()); | |
| 323 if (container.has_update_disabled()) { | |
| 324 policies->Set(key::kDeviceAutoUpdateDisabled, | |
| 325 POLICY_LEVEL_MANDATORY, | |
| 326 POLICY_SCOPE_MACHINE, | |
| 327 Value::CreateBooleanValue(container.update_disabled())); | |
| 328 } | |
| 329 | |
| 330 if (container.has_target_version_prefix()) { | |
| 331 policies->Set(key::kDeviceTargetVersionPrefix, | |
| 332 POLICY_LEVEL_MANDATORY, | |
| 333 POLICY_SCOPE_MACHINE, | |
| 334 Value::CreateStringValue( | |
| 335 container.target_version_prefix())); | |
| 336 } | |
| 337 | |
| 338 // target_version_display_name is not actually a policy, but a display | |
| 339 // string for target_version_prefix, so we ignore it. | |
| 340 | |
| 341 if (container.has_scatter_factor_in_seconds()) { | |
| 342 policies->Set(key::kDeviceUpdateScatterFactor, | |
| 343 POLICY_LEVEL_MANDATORY, | |
| 344 POLICY_SCOPE_MACHINE, | |
| 345 Value::CreateIntegerValue( | |
| 346 container.scatter_factor_in_seconds())); | |
| 347 } | |
| 348 | |
| 349 if (container.allowed_connection_types_size()) { | |
| 350 ListValue* allowed_connection_types = new ListValue(); | |
| 351 RepeatedField<int>::const_iterator entry; | |
| 352 for (entry = container.allowed_connection_types().begin(); | |
| 353 entry != container.allowed_connection_types().end(); | |
| 354 ++entry) { | |
| 355 base::Value* value = DecodeConnectionType(*entry); | |
| 356 if (value) | |
| 357 allowed_connection_types->Append(value); | |
| 358 } | |
| 359 policies->Set(key::kDeviceUpdateAllowedConnectionTypes, | |
| 360 POLICY_LEVEL_MANDATORY, | |
| 361 POLICY_SCOPE_MACHINE, | |
| 362 allowed_connection_types); | |
| 363 } | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 void DecodeGenericPolicies(const em::ChromeDeviceSettingsProto& policy, | |
| 368 PolicyMap* policies) { | |
| 369 if (policy.has_device_policy_refresh_rate()) { | |
| 370 const em::DevicePolicyRefreshRateProto& container( | |
| 371 policy.device_policy_refresh_rate()); | |
| 372 if (container.has_device_policy_refresh_rate()) { | |
| 373 policies->Set(key::kDevicePolicyRefreshRate, | |
| 374 POLICY_LEVEL_MANDATORY, | |
| 375 POLICY_SCOPE_MACHINE, | |
| 376 DecodeIntegerValue(container.device_policy_refresh_rate())); | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 if (policy.has_metrics_enabled()) { | |
| 381 const em::MetricsEnabledProto& container(policy.metrics_enabled()); | |
| 382 if (container.has_metrics_enabled()) { | |
| 383 policies->Set(key::kDeviceMetricsReportingEnabled, | |
| 384 POLICY_LEVEL_MANDATORY, | |
| 385 POLICY_SCOPE_MACHINE, | |
| 386 Value::CreateBooleanValue(container.metrics_enabled())); | |
| 387 } | |
| 388 } | |
| 389 | |
| 390 if (policy.has_start_up_urls()) { | |
| 391 const em::StartUpUrlsProto& container(policy.start_up_urls()); | |
| 392 if (container.start_up_urls_size()) { | |
| 393 ListValue* urls = new ListValue(); | |
| 394 RepeatedPtrField<std::string>::const_iterator entry; | |
| 395 for (entry = container.start_up_urls().begin(); | |
| 396 entry != container.start_up_urls().end(); | |
| 397 ++entry) { | |
| 398 urls->Append(Value::CreateStringValue(*entry)); | |
| 399 } | |
| 400 policies->Set(key::kDeviceStartUpUrls, | |
| 401 POLICY_LEVEL_MANDATORY, | |
| 402 POLICY_SCOPE_MACHINE, | |
| 403 urls); | |
| 404 } | |
| 405 } | |
| 406 | |
| 407 if (policy.has_system_timezone()) { | |
| 408 if (policy.system_timezone().has_timezone()) { | |
| 409 policies->Set(key::kSystemTimezone, | |
| 410 POLICY_LEVEL_MANDATORY, | |
| 411 POLICY_SCOPE_MACHINE, | |
| 412 Value::CreateStringValue( | |
| 413 policy.system_timezone().timezone())); | |
| 414 } | |
| 415 } | |
| 416 } | |
| 417 | |
| 418 } // namespace | |
| 419 | |
| 420 void DecodeDevicePolicy(const em::ChromeDeviceSettingsProto& policy, | |
| 421 PolicyMap* policies, | |
| 422 EnterpriseInstallAttributes* install_attributes) { | |
| 423 // Decode the various groups of policies. | |
| 424 DecodeLoginPolicies(policy, policies); | |
| 425 DecodeKioskPolicies(policy, policies, install_attributes); | |
| 426 DecodeNetworkPolicies(policy, policies, install_attributes); | |
| 427 DecodeReportingPolicies(policy, policies); | |
| 428 DecodeAutoUpdatePolicies(policy, policies); | |
| 429 DecodeGenericPolicies(policy, policies); | |
| 430 } | |
| 431 | |
| 432 } // namespace policy | |
| OLD | NEW |