1 // Copyright 2013 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.
5 #include "chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/strings/string_util.h"
16 #include "base/sys_info.h"
17 #include "base/values.h"
18 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
19 #include "chrome/browser/chromeos/settings/cros_settings.h"
20 #include "chrome/grit/chromium_strings.h"
21 #include "chrome/grit/generated_resources.h"
22 #include "chromeos/chromeos_switches.h"
23 #include "chromeos/settings/cros_settings_names.h"
24 #include "components/crx_file/id_util.h"
25 #include "components/user_manager/user_manager.h"
26 #include "content/public/browser/web_ui.h"
27 #include "content/public/browser/web_ui_data_source.h"
28 #include "extensions/common/extension_urls.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/webui/web_ui_util.h"
37 // Populates app info dictionary with |app_data|.
38 void PopulateAppDict(const KioskAppManager::App
& app_data
,
39 base::DictionaryValue
* app_dict
) {
40 std::string
icon_url("chrome://theme/IDR_APP_DEFAULT_ICON");
42 // TODO(xiyuan): Replace data url with a URLDataSource.
43 if (!app_data
.icon
.isNull())
44 icon_url
= webui::GetBitmapDataUrl(*app_data
.icon
.bitmap());
46 // The items which are to be written into app_dict are also described in
47 // chrome/browser/resources/extensions/chromeos/kiosk_app_list.js in @typedef
48 // for AppDict. Please update it whenever you add or remove any keys here.
49 app_dict
->SetString("id", app_data
.app_id
);
50 app_dict
->SetString("name", app_data
.name
);
51 app_dict
->SetString("iconURL", icon_url
);
54 KioskAppManager::Get()->GetAutoLaunchApp() == app_data
.app_id
&&
55 (KioskAppManager::Get()->IsAutoLaunchEnabled() ||
56 KioskAppManager::Get()->IsAutoLaunchRequested()));
57 app_dict
->SetBoolean("isLoading", app_data
.is_loading
);
60 // Sanitize app id input value and extracts app id out of it.
61 // Returns false if an app id could not be derived out of the input.
62 bool ExtractsAppIdFromInput(const std::string
& input
,
63 std::string
* app_id
) {
64 if (crx_file::id_util::IdIsValid(input
)) {
69 GURL webstore_url
= GURL(input
);
70 if (!webstore_url
.is_valid())
73 GURL webstore_base_url
=
74 GURL(extension_urls::GetWebstoreItemDetailURLPrefix());
76 if (webstore_url
.scheme() != webstore_base_url
.scheme() ||
77 webstore_url
.host() != webstore_base_url
.host() ||
78 !base::StartsWith(webstore_url
.path(), webstore_base_url
.path(),
79 base::CompareCase::SENSITIVE
)) {
83 const std::string path
= webstore_url
.path();
84 const size_t last_slash
= path
.rfind('/');
85 if (last_slash
== std::string::npos
)
88 const std::string candidate_id
= path
.substr(last_slash
+ 1);
89 if (!crx_file::id_util::IdIsValid(candidate_id
))
92 *app_id
= candidate_id
;
98 KioskAppsHandler::KioskAppsHandler(OwnerSettingsServiceChromeOS
* service
)
99 : kiosk_app_manager_(KioskAppManager::Get()),
101 is_kiosk_enabled_(false),
102 is_auto_launch_enabled_(false),
103 owner_settings_service_(service
),
104 weak_ptr_factory_(this) {
105 kiosk_app_manager_
->AddObserver(this);
108 KioskAppsHandler::~KioskAppsHandler() {
109 kiosk_app_manager_
->RemoveObserver(this);
112 void KioskAppsHandler::RegisterMessages() {
113 web_ui()->RegisterMessageCallback("initializeKioskAppSettings",
114 base::Bind(&KioskAppsHandler::HandleInitializeKioskAppSettings
,
115 base::Unretained(this)));
116 web_ui()->RegisterMessageCallback("getKioskAppSettings",
117 base::Bind(&KioskAppsHandler::HandleGetKioskAppSettings
,
118 base::Unretained(this)));
119 web_ui()->RegisterMessageCallback("addKioskApp",
120 base::Bind(&KioskAppsHandler::HandleAddKioskApp
,
121 base::Unretained(this)));
122 web_ui()->RegisterMessageCallback("removeKioskApp",
123 base::Bind(&KioskAppsHandler::HandleRemoveKioskApp
,
124 base::Unretained(this)));
125 web_ui()->RegisterMessageCallback("enableKioskAutoLaunch",
126 base::Bind(&KioskAppsHandler::HandleEnableKioskAutoLaunch
,
127 base::Unretained(this)));
128 web_ui()->RegisterMessageCallback("disableKioskAutoLaunch",
129 base::Bind(&KioskAppsHandler::HandleDisableKioskAutoLaunch
,
130 base::Unretained(this)));
131 web_ui()->RegisterMessageCallback("setDisableBailoutShortcut",
132 base::Bind(&KioskAppsHandler::HandleSetDisableBailoutShortcut
,
133 base::Unretained(this)));
136 void KioskAppsHandler::GetLocalizedValues(content::WebUIDataSource
* source
) {
139 l10n_util::GetStringUTF16(IDS_EXTENSIONS_ADD_KIOSK_APP_BUTTON
));
142 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_OVERLAY_TITLE
));
145 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ADD_APP
));
147 "kioskAppIdEditHint",
148 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ADD_APP_HINT
));
150 "enableAutoLaunchButton",
151 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ENABLE_AUTO_LAUNCH
));
153 "disableAutoLaunchButton",
154 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_DISABLE_AUTO_LAUNCH
));
157 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_AUTO_LAUNCH
));
160 l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_INVALID_APP
));
162 "kioskDiableBailoutShortcutLabel",
163 l10n_util::GetStringUTF16(
164 IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_LABEL
));
166 "kioskDisableBailoutShortcutWarningBold",
167 l10n_util::GetStringUTF16(
168 IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_BOLD
));
169 const base::string16 product_os_name
=
170 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME
);
172 "kioskDisableBailoutShortcutWarning",
173 l10n_util::GetStringFUTF16(
174 IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_FORMAT
,
177 "kioskDisableBailoutShortcutConfirm",
178 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL
));
180 "kioskDisableBailoutShortcutCancel",
181 l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL
));
182 source
->AddString("done", l10n_util::GetStringUTF16(IDS_DONE
));
183 source
->AddString("add", l10n_util::GetStringUTF16(IDS_ADD
));
186 void KioskAppsHandler::OnKioskAppDataChanged(const std::string
& app_id
) {
190 void KioskAppsHandler::OnKioskAppDataLoadFailure(const std::string
& app_id
) {
194 void KioskAppsHandler::OnKioskExtensionLoadedInCache(
195 const std::string
& app_id
) {
199 void KioskAppsHandler::OnKioskExtensionDownloadFailed(
200 const std::string
& app_id
) {
204 void KioskAppsHandler::OnGetConsumerKioskAutoLaunchStatus(
205 chromeos::KioskAppManager::ConsumerKioskAutoLaunchStatus status
) {
207 is_kiosk_enabled_
= user_manager::UserManager::Get()->IsCurrentUserOwner() ||
208 !base::SysInfo::IsRunningOnChromeOS();
210 is_auto_launch_enabled_
=
211 status
== KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_ENABLED
||
212 !base::SysInfo::IsRunningOnChromeOS();
214 if (is_kiosk_enabled_
) {
215 base::DictionaryValue kiosk_params
;
216 kiosk_params
.SetBoolean("kioskEnabled", is_kiosk_enabled_
);
217 kiosk_params
.SetBoolean("autoLaunchEnabled", is_auto_launch_enabled_
);
218 web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.enableKiosk",
224 void KioskAppsHandler::OnKioskAppsSettingsChanged() {
225 SendKioskAppSettings();
228 void KioskAppsHandler::SendKioskAppSettings() {
229 if (!initialized_
|| !is_kiosk_enabled_
)
232 bool enable_bailout_shortcut
;
233 if (!CrosSettings::Get()->GetBoolean(
234 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled
,
235 &enable_bailout_shortcut
)) {
236 enable_bailout_shortcut
= true;
239 base::DictionaryValue settings
;
240 settings
.SetBoolean("disableBailout", !enable_bailout_shortcut
);
241 settings
.SetBoolean("hasAutoLaunchApp",
242 !kiosk_app_manager_
->GetAutoLaunchApp().empty());
244 KioskAppManager::Apps apps
;
245 kiosk_app_manager_
->GetApps(&apps
);
247 scoped_ptr
<base::ListValue
> apps_list(new base::ListValue
);
248 for (size_t i
= 0; i
< apps
.size(); ++i
) {
249 const KioskAppManager::App
& app_data
= apps
[i
];
251 scoped_ptr
<base::DictionaryValue
> app_info(new base::DictionaryValue
);
252 PopulateAppDict(app_data
, app_info
.get());
253 apps_list
->Append(app_info
.release());
255 settings
.SetWithoutPathExpansion("apps", apps_list
.release());
257 web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.setSettings",
261 void KioskAppsHandler::HandleInitializeKioskAppSettings(
262 const base::ListValue
* args
) {
263 KioskAppManager::Get()->GetConsumerKioskAutoLaunchStatus(
264 base::Bind(&KioskAppsHandler::OnGetConsumerKioskAutoLaunchStatus
,
265 weak_ptr_factory_
.GetWeakPtr()));
268 void KioskAppsHandler::HandleGetKioskAppSettings(const base::ListValue
* args
) {
269 SendKioskAppSettings();
273 void KioskAppsHandler::HandleAddKioskApp(const base::ListValue
* args
) {
274 if (!initialized_
|| !is_kiosk_enabled_
)
278 CHECK(args
->GetString(0, &input
));
281 if (!ExtractsAppIdFromInput(input
, &app_id
)) {
282 OnKioskAppDataLoadFailure(input
);
286 kiosk_app_manager_
->AddApp(app_id
, owner_settings_service_
);
289 void KioskAppsHandler::HandleRemoveKioskApp(const base::ListValue
* args
) {
290 if (!initialized_
|| !is_kiosk_enabled_
)
294 CHECK(args
->GetString(0, &app_id
));
296 kiosk_app_manager_
->RemoveApp(app_id
, owner_settings_service_
);
299 void KioskAppsHandler::HandleEnableKioskAutoLaunch(
300 const base::ListValue
* args
) {
301 if (!initialized_
|| !is_kiosk_enabled_
|| !is_auto_launch_enabled_
)
305 CHECK(args
->GetString(0, &app_id
));
307 kiosk_app_manager_
->SetAutoLaunchApp(app_id
, owner_settings_service_
);
310 void KioskAppsHandler::HandleDisableKioskAutoLaunch(
311 const base::ListValue
* args
) {
312 if (!initialized_
|| !is_kiosk_enabled_
|| !is_auto_launch_enabled_
)
316 CHECK(args
->GetString(0, &app_id
));
318 std::string startup_app_id
= kiosk_app_manager_
->GetAutoLaunchApp();
319 if (startup_app_id
!= app_id
)
322 kiosk_app_manager_
->SetAutoLaunchApp("", owner_settings_service_
);
325 void KioskAppsHandler::HandleSetDisableBailoutShortcut(
326 const base::ListValue
* args
) {
327 if (!initialized_
|| !is_kiosk_enabled_
)
330 bool disable_bailout_shortcut
;
331 CHECK(args
->GetBoolean(0, &disable_bailout_shortcut
));
333 owner_settings_service_
->SetBoolean(
334 kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled
,
335 !disable_bailout_shortcut
);
338 void KioskAppsHandler::UpdateApp(const std::string
& app_id
) {
339 KioskAppManager::App app_data
;
340 if (!kiosk_app_manager_
->GetApp(app_id
, &app_data
))
343 base::DictionaryValue app_dict
;
344 PopulateAppDict(app_data
, &app_dict
);
346 web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.updateApp",
350 void KioskAppsHandler::ShowError(const std::string
& app_id
) {
351 base::StringValue
app_id_value(app_id
);
352 web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.showError",
355 kiosk_app_manager_
->RemoveApp(app_id
, owner_settings_service_
);
358 } // namespace chromeos