3fdaecf29bafcd48407a226b62f26d080cd733d3
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / extensions / chromeos / kiosk_apps_handler.cc
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.
4
5 #include "chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h"
6
7 #include <algorithm>
8 #include <set>
9 #include <string>
10 #include <vector>
11
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/sys_info.h"
16 #include "base/values.h"
17 #include "chrome/browser/chromeos/login/user_manager.h"
18 #include "chrome/browser/chromeos/settings/cros_settings.h"
19 #include "chrome/common/extensions/extension_constants.h"
20 #include "chromeos/chromeos_switches.h"
21 #include "chromeos/settings/cros_settings_names.h"
22 #include "content/public/browser/web_ui.h"
23 #include "content/public/browser/web_ui_data_source.h"
24 #include "extensions/common/extension.h"
25 #include "grit/chromium_strings.h"
26 #include "grit/generated_resources.h"
27 #include "ui/base/l10n/l10n_util.h"
28 #include "ui/base/webui/web_ui_util.h"
29 #include "url/gurl.h"
30
31 namespace chromeos {
32
33 namespace {
34
35 // Populates app info dictionary with |app_data|.
36 void PopulateAppDict(const KioskAppManager::App& app_data,
37                      base::DictionaryValue* app_dict) {
38   std::string icon_url("chrome://theme/IDR_APP_DEFAULT_ICON");
39
40   // TODO(xiyuan): Replace data url with a URLDataSource.
41   if (!app_data.icon.isNull())
42     icon_url = webui::GetBitmapDataUrl(*app_data.icon.bitmap());
43
44   app_dict->SetString("id", app_data.app_id);
45   app_dict->SetString("name", app_data.name);
46   app_dict->SetString("iconURL", icon_url);
47   app_dict->SetBoolean(
48       "autoLaunch",
49       KioskAppManager::Get()->GetAutoLaunchApp() == app_data.app_id &&
50       (KioskAppManager::Get()->IsAutoLaunchEnabled() ||
51           KioskAppManager::Get()->IsAutoLaunchRequested()));
52   app_dict->SetBoolean("isLoading", app_data.is_loading);
53 }
54
55 // Sanitize app id input value and extracts app id out of it.
56 // Returns false if an app id could not be derived out of the input.
57 bool ExtractsAppIdFromInput(const std::string& input,
58                             std::string* app_id) {
59   if (extensions::Extension::IdIsValid(input)) {
60     *app_id = input;
61     return true;
62   }
63
64   GURL webstore_url = GURL(input);
65   if (!webstore_url.is_valid())
66     return false;
67
68   GURL webstore_base_url =
69       GURL(extension_urls::GetWebstoreItemDetailURLPrefix());
70
71   if (webstore_url.scheme() != webstore_base_url.scheme() ||
72       webstore_url.host() != webstore_base_url.host() ||
73       !StartsWithASCII(
74           webstore_url.path(), webstore_base_url.path(), true)) {
75     return false;
76   }
77
78   const std::string path = webstore_url.path();
79   const size_t last_slash = path.rfind('/');
80   if (last_slash == std::string::npos)
81     return false;
82
83   const std::string candidate_id = path.substr(last_slash + 1);
84   if (!extensions::Extension::IdIsValid(candidate_id))
85     return false;
86
87   *app_id = candidate_id;
88   return true;
89 }
90
91 }  // namespace
92
93 KioskAppsHandler::KioskAppsHandler()
94     : kiosk_app_manager_(KioskAppManager::Get()),
95       initialized_(false),
96       is_kiosk_enabled_(false),
97       weak_ptr_factory_(this) {
98   kiosk_app_manager_->AddObserver(this);
99 }
100
101 KioskAppsHandler::~KioskAppsHandler() {
102   kiosk_app_manager_->RemoveObserver(this);
103 }
104
105 void KioskAppsHandler::RegisterMessages() {
106   web_ui()->RegisterMessageCallback("initializeKioskAppSettings",
107       base::Bind(&KioskAppsHandler::HandleInitializeKioskAppSettings,
108                  base::Unretained(this)));
109   web_ui()->RegisterMessageCallback("getKioskAppSettings",
110       base::Bind(&KioskAppsHandler::HandleGetKioskAppSettings,
111                  base::Unretained(this)));
112   web_ui()->RegisterMessageCallback("addKioskApp",
113       base::Bind(&KioskAppsHandler::HandleAddKioskApp,
114                  base::Unretained(this)));
115   web_ui()->RegisterMessageCallback("removeKioskApp",
116       base::Bind(&KioskAppsHandler::HandleRemoveKioskApp,
117                  base::Unretained(this)));
118   web_ui()->RegisterMessageCallback("enableKioskAutoLaunch",
119       base::Bind(&KioskAppsHandler::HandleEnableKioskAutoLaunch,
120                  base::Unretained(this)));
121   web_ui()->RegisterMessageCallback("disableKioskAutoLaunch",
122       base::Bind(&KioskAppsHandler::HandleDisableKioskAutoLaunch,
123                  base::Unretained(this)));
124   web_ui()->RegisterMessageCallback("setDisableBailoutShortcut",
125       base::Bind(&KioskAppsHandler::HandleSetDisableBailoutShortcut,
126                  base::Unretained(this)));
127 }
128
129 void KioskAppsHandler::GetLocalizedValues(content::WebUIDataSource* source) {
130   source->AddString(
131       "addKioskAppButton",
132       l10n_util::GetStringUTF16(IDS_EXTENSIONS_ADD_KIOSK_APP_BUTTON));
133   source->AddString(
134       "kioskOverlayTitle",
135       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_OVERLAY_TITLE));
136   source->AddString(
137       "addKioskApp",
138       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ADD_APP));
139   source->AddString(
140       "kioskAppIdEditHint",
141       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ADD_APP_HINT));
142   source->AddString(
143       "enableAutoLaunchButton",
144       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ENABLE_AUTO_LAUNCH));
145   source->AddString(
146       "disableAutoLaunchButton",
147       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_DISABLE_AUTO_LAUNCH));
148   source->AddString(
149       "autoLaunch",
150       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_AUTO_LAUNCH));
151   source->AddString(
152       "invalidApp",
153       l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_INVALID_APP));
154   source->AddString(
155       "kioskDiableBailoutShortcutLabel",
156       l10n_util::GetStringUTF16(
157           IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_LABEL));
158   source->AddString(
159       "kioskDisableBailoutShortcutWarningBold",
160       l10n_util::GetStringUTF16(
161           IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_BOLD));
162   const base::string16 product_os_name =
163       l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME);
164   source->AddString(
165       "kioskDisableBailoutShortcutWarning",
166       l10n_util::GetStringFUTF16(
167           IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_FORMAT,
168           product_os_name));
169   source->AddString(
170       "kioskDisableBailoutShortcutConfirm",
171       l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL));
172   source->AddString(
173       "kioskDisableBailoutShortcutCancel",
174       l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL));
175   source->AddString("done", l10n_util::GetStringUTF16(IDS_DONE));
176   source->AddString("add", l10n_util::GetStringUTF16(IDS_ADD));
177 }
178
179 void KioskAppsHandler::OnKioskAppDataChanged(const std::string& app_id) {
180   KioskAppManager::App app_data;
181   if (!kiosk_app_manager_->GetApp(app_id, &app_data))
182     return;
183
184   base::DictionaryValue app_dict;
185   PopulateAppDict(app_data, &app_dict);
186
187   web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.updateApp",
188                                    app_dict);
189 }
190
191 void KioskAppsHandler::OnKioskAppDataLoadFailure(const std::string& app_id) {
192   base::StringValue app_id_value(app_id);
193   web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.showError",
194                                    app_id_value);
195 }
196
197
198 void KioskAppsHandler::OnGetConsumerKioskModeStatus(
199     chromeos::KioskAppManager::ConsumerKioskModeStatus status) {
200   initialized_ = true;
201   is_kiosk_enabled_ =
202       ((status == KioskAppManager::CONSUMER_KIOSK_MODE_ENABLED) &&
203           chromeos::UserManager::Get()->IsCurrentUserOwner()) ||
204       !base::SysInfo::IsRunningOnChromeOS();
205
206   if (is_kiosk_enabled_) {
207     base::FundamentalValue enabled(is_kiosk_enabled_);
208     web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.enableKiosk",
209                                      enabled);
210   }
211 }
212
213
214 void KioskAppsHandler::OnKioskAppsSettingsChanged() {
215   SendKioskAppSettings();
216 }
217
218 void KioskAppsHandler::SendKioskAppSettings() {
219   if (!initialized_ || !is_kiosk_enabled_)
220     return;
221
222   bool enable_bailout_shortcut;
223   if (!CrosSettings::Get()->GetBoolean(
224           kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled,
225           &enable_bailout_shortcut)) {
226     enable_bailout_shortcut = true;
227   }
228
229   base::DictionaryValue settings;
230   settings.SetBoolean("disableBailout", !enable_bailout_shortcut);
231
232   KioskAppManager::Apps apps;
233   kiosk_app_manager_->GetApps(&apps);
234
235   scoped_ptr<base::ListValue> apps_list(new base::ListValue);
236   for (size_t i = 0; i < apps.size(); ++i) {
237     const KioskAppManager::App& app_data = apps[i];
238
239     scoped_ptr<base::DictionaryValue> app_info(new base::DictionaryValue);
240     PopulateAppDict(app_data, app_info.get());
241     apps_list->Append(app_info.release());
242   }
243   settings.SetWithoutPathExpansion("apps", apps_list.release());
244
245   web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.setSettings",
246                                    settings);
247 }
248
249 void KioskAppsHandler::HandleInitializeKioskAppSettings(
250     const base::ListValue* args) {
251   KioskAppManager::Get()->GetConsumerKioskModeStatus(
252       base::Bind(&KioskAppsHandler::OnGetConsumerKioskModeStatus,
253                  weak_ptr_factory_.GetWeakPtr()));
254 }
255
256 void KioskAppsHandler::HandleGetKioskAppSettings(const base::ListValue* args) {
257   SendKioskAppSettings();
258 }
259
260
261 void KioskAppsHandler::HandleAddKioskApp(const base::ListValue* args) {
262   if (!initialized_ || !is_kiosk_enabled_)
263     return;
264
265   std::string input;
266   CHECK(args->GetString(0, &input));
267
268   std::string app_id;
269   if (!ExtractsAppIdFromInput(input, &app_id)) {
270     OnKioskAppDataLoadFailure(input);
271     return;
272   }
273
274   kiosk_app_manager_->AddApp(app_id);
275 }
276
277 void KioskAppsHandler::HandleRemoveKioskApp(const base::ListValue* args) {
278   if (!initialized_ || !is_kiosk_enabled_)
279     return;
280
281   std::string app_id;
282   CHECK(args->GetString(0, &app_id));
283
284   kiosk_app_manager_->RemoveApp(app_id);
285 }
286
287 void KioskAppsHandler::HandleEnableKioskAutoLaunch(
288     const base::ListValue* args) {
289   if (!initialized_ || !is_kiosk_enabled_)
290     return;
291
292   std::string app_id;
293   CHECK(args->GetString(0, &app_id));
294
295   kiosk_app_manager_->SetAutoLaunchApp(app_id);
296 }
297
298 void KioskAppsHandler::HandleDisableKioskAutoLaunch(
299     const base::ListValue* args) {
300   if (!initialized_ || !is_kiosk_enabled_)
301     return;
302
303   std::string app_id;
304   CHECK(args->GetString(0, &app_id));
305
306   std::string startup_app_id = kiosk_app_manager_->GetAutoLaunchApp();
307   if (startup_app_id != app_id)
308     return;
309
310   kiosk_app_manager_->SetAutoLaunchApp("");
311 }
312
313 void KioskAppsHandler::HandleSetDisableBailoutShortcut(
314     const base::ListValue* args) {
315   if (!initialized_ || !is_kiosk_enabled_)
316     return;
317
318   bool disable_bailout_shortcut;
319   CHECK(args->GetBoolean(0, &disable_bailout_shortcut));
320
321   CrosSettings::Get()->SetBoolean(
322       kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled,
323       !disable_bailout_shortcut);
324 }
325
326 }  // namespace chromeos