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 if (policy.has_allow_redeem_offers()) { | |
418 const em::AllowRedeemChromeOsRegistrationOffersProto& container( | |
419 policy.allow_redeem_offers()); | |
420 if (container.has_allow_redeem_offers()) { | |
421 policies->Set(key::kDeviceAllowRedeemChromeOsRegistrationOffers, | |
422 POLICY_LEVEL_MANDATORY, | |
423 POLICY_SCOPE_MACHINE, | |
424 Value::CreateBooleanValue( | |
425 container.allow_redeem_offers())); | |
426 } | |
427 } | |
428 | |
429 if (policy.has_start_up_flags()) { | |
430 const em::StartUpFlagsProto& container(policy.start_up_flags()); | |
431 if (container.flags_size()) { | |
432 ListValue* flags = new ListValue(); | |
433 RepeatedPtrField<std::string>::const_iterator entry; | |
434 for (entry = container.flags().begin(); | |
435 entry != container.flags().end(); | |
436 ++entry) { | |
437 flags->Append(Value::CreateStringValue(*entry)); | |
438 } | |
439 policies->Set(key::kDeviceStartUpFlags, | |
440 POLICY_LEVEL_MANDATORY, | |
441 POLICY_SCOPE_MACHINE, | |
442 flags); | |
443 } | |
444 } | |
445 } | |
446 | |
447 } // namespace | |
448 | |
449 void DecodeDevicePolicy(const em::ChromeDeviceSettingsProto& policy, | |
450 PolicyMap* policies, | |
451 EnterpriseInstallAttributes* install_attributes) { | |
452 // Decode the various groups of policies. | |
453 DecodeLoginPolicies(policy, policies); | |
454 DecodeKioskPolicies(policy, policies, install_attributes); | |
455 DecodeNetworkPolicies(policy, policies, install_attributes); | |
456 DecodeReportingPolicies(policy, policies); | |
457 DecodeAutoUpdatePolicies(policy, policies); | |
458 DecodeGenericPolicies(policy, policies); | |
459 } | |
460 | |
461 } // namespace policy | |
OLD | NEW |