| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.h" |
| |
| #include <algorithm> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/sys_info.h" |
| #include "base/values.h" |
| #include "chrome/browser/chromeos/login/user_manager.h" |
| #include "chrome/browser/chromeos/settings/cros_settings.h" |
| #include "chrome/common/extensions/extension.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "chromeos/settings/cros_settings_names.h" |
| #include "content/public/browser/web_ui.h" |
| #include "content/public/browser/web_ui_data_source.h" |
| #include "grit/chromium_strings.h" |
| #include "grit/generated_resources.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/webui/web_ui_util.h" |
| #include "url/gurl.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| // Populates app info dictionary with |app_data|. |
| void PopulateAppDict(const KioskAppManager::App& app_data, |
| base::DictionaryValue* app_dict) { |
| std::string icon_url("chrome://theme/IDR_APP_DEFAULT_ICON"); |
| |
| // TODO(xiyuan): Replace data url with a URLDataSource. |
| if (!app_data.icon.isNull()) |
| icon_url = webui::GetBitmapDataUrl(*app_data.icon.bitmap()); |
| |
| app_dict->SetString("id", app_data.app_id); |
| app_dict->SetString("name", app_data.name); |
| app_dict->SetString("iconURL", icon_url); |
| app_dict->SetBoolean( |
| "autoLaunch", |
| KioskAppManager::Get()->GetAutoLaunchApp() == app_data.app_id && |
| (KioskAppManager::Get()->IsAutoLaunchEnabled() || |
| KioskAppManager::Get()->IsAutoLaunchRequested())); |
| app_dict->SetBoolean("isLoading", app_data.is_loading); |
| } |
| |
| // Sanitize app id input value and extracts app id out of it. |
| // Returns false if an app id could not be derived out of the input. |
| bool ExtractsAppIdFromInput(const std::string& input, |
| std::string* app_id) { |
| if (extensions::Extension::IdIsValid(input)) { |
| *app_id = input; |
| return true; |
| } |
| |
| GURL webstore_url = GURL(input); |
| if (!webstore_url.is_valid()) |
| return false; |
| |
| GURL webstore_base_url = |
| GURL(extension_urls::GetWebstoreItemDetailURLPrefix()); |
| |
| if (webstore_url.scheme() != webstore_base_url.scheme() || |
| webstore_url.host() != webstore_base_url.host() || |
| !StartsWithASCII( |
| webstore_url.path(), webstore_base_url.path(), true)) { |
| return false; |
| } |
| |
| const std::string path = webstore_url.path(); |
| const size_t last_slash = path.rfind('/'); |
| if (last_slash == std::string::npos) |
| return false; |
| |
| const std::string candidate_id = path.substr(last_slash + 1); |
| if (!extensions::Extension::IdIsValid(candidate_id)) |
| return false; |
| |
| *app_id = candidate_id; |
| return true; |
| } |
| |
| } // namespace |
| |
| KioskAppsHandler::KioskAppsHandler() |
| : kiosk_app_manager_(KioskAppManager::Get()), |
| initialized_(false), |
| is_kiosk_enabled_(false), |
| weak_ptr_factory_(this) { |
| kiosk_app_manager_->AddObserver(this); |
| } |
| |
| KioskAppsHandler::~KioskAppsHandler() { |
| kiosk_app_manager_->RemoveObserver(this); |
| } |
| |
| void KioskAppsHandler::RegisterMessages() { |
| web_ui()->RegisterMessageCallback("initializeKioskAppSettings", |
| base::Bind(&KioskAppsHandler::HandleInitializeKioskAppSettings, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback("getKioskAppSettings", |
| base::Bind(&KioskAppsHandler::HandleGetKioskAppSettings, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback("addKioskApp", |
| base::Bind(&KioskAppsHandler::HandleAddKioskApp, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback("removeKioskApp", |
| base::Bind(&KioskAppsHandler::HandleRemoveKioskApp, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback("enableKioskAutoLaunch", |
| base::Bind(&KioskAppsHandler::HandleEnableKioskAutoLaunch, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback("disableKioskAutoLaunch", |
| base::Bind(&KioskAppsHandler::HandleDisableKioskAutoLaunch, |
| base::Unretained(this))); |
| web_ui()->RegisterMessageCallback("setDisableBailoutShortcut", |
| base::Bind(&KioskAppsHandler::HandleSetDisableBailoutShortcut, |
| base::Unretained(this))); |
| } |
| |
| void KioskAppsHandler::GetLocalizedValues(content::WebUIDataSource* source) { |
| source->AddString( |
| "addKioskAppButton", |
| l10n_util::GetStringUTF16(IDS_EXTENSIONS_ADD_KIOSK_APP_BUTTON)); |
| source->AddString( |
| "kioskOverlayTitle", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_OVERLAY_TITLE)); |
| source->AddString( |
| "addKioskApp", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ADD_APP)); |
| source->AddString( |
| "kioskAppIdEditHint", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ADD_APP_HINT)); |
| source->AddString( |
| "enableAutoLaunchButton", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_ENABLE_AUTO_LAUNCH)); |
| source->AddString( |
| "disableAutoLaunchButton", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_DISABLE_AUTO_LAUNCH)); |
| source->AddString( |
| "autoLaunch", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_AUTO_LAUNCH)); |
| source->AddString( |
| "invalidApp", |
| l10n_util::GetStringUTF16(IDS_OPTIONS_KIOSK_INVALID_APP)); |
| source->AddString( |
| "kioskDiableBailoutShortcutLabel", |
| l10n_util::GetStringUTF16( |
| IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_LABEL)); |
| source->AddString( |
| "kioskDisableBailoutShortcutWarningBold", |
| l10n_util::GetStringUTF16( |
| IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_BOLD)); |
| const string16 product_os_name = |
| l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME); |
| source->AddString( |
| "kioskDisableBailoutShortcutWarning", |
| l10n_util::GetStringFUTF16( |
| IDS_OPTIONS_KIOSK_DISABLE_BAILOUT_SHORTCUT_WARNING_FORMAT, |
| product_os_name)); |
| source->AddString( |
| "kioskDisableBailoutShortcutConfirm", |
| l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL)); |
| source->AddString( |
| "kioskDisableBailoutShortcutCancel", |
| l10n_util::GetStringUTF16(IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL)); |
| source->AddString("done", l10n_util::GetStringUTF16(IDS_DONE)); |
| source->AddString("add", l10n_util::GetStringUTF16(IDS_ADD)); |
| } |
| |
| void KioskAppsHandler::OnKioskAppDataChanged(const std::string& app_id) { |
| KioskAppManager::App app_data; |
| if (!kiosk_app_manager_->GetApp(app_id, &app_data)) |
| return; |
| |
| base::DictionaryValue app_dict; |
| PopulateAppDict(app_data, &app_dict); |
| |
| web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.updateApp", |
| app_dict); |
| } |
| |
| void KioskAppsHandler::OnKioskAppDataLoadFailure(const std::string& app_id) { |
| base::StringValue app_id_value(app_id); |
| web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.showError", |
| app_id_value); |
| } |
| |
| |
| void KioskAppsHandler::OnGetConsumerKioskModeStatus( |
| chromeos::KioskAppManager::ConsumerKioskModeStatus status) { |
| initialized_ = true; |
| is_kiosk_enabled_ = |
| ((status == KioskAppManager::CONSUMER_KIOSK_MODE_ENABLED) && |
| chromeos::UserManager::Get()->IsCurrentUserOwner()) || |
| !base::SysInfo::IsRunningOnChromeOS(); |
| |
| if (is_kiosk_enabled_) { |
| base::FundamentalValue enabled(is_kiosk_enabled_); |
| web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.enableKiosk", |
| enabled); |
| } |
| } |
| |
| |
| void KioskAppsHandler::OnKioskAppsSettingsChanged() { |
| SendKioskAppSettings(); |
| } |
| |
| void KioskAppsHandler::SendKioskAppSettings() { |
| if (!initialized_ || !is_kiosk_enabled_) |
| return; |
| |
| bool enable_bailout_shortcut; |
| if (!CrosSettings::Get()->GetBoolean( |
| kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, |
| &enable_bailout_shortcut)) { |
| enable_bailout_shortcut = true; |
| } |
| |
| base::DictionaryValue settings; |
| settings.SetBoolean("disableBailout", !enable_bailout_shortcut); |
| |
| KioskAppManager::Apps apps; |
| kiosk_app_manager_->GetApps(&apps); |
| |
| scoped_ptr<base::ListValue> apps_list(new base::ListValue); |
| for (size_t i = 0; i < apps.size(); ++i) { |
| const KioskAppManager::App& app_data = apps[i]; |
| |
| scoped_ptr<base::DictionaryValue> app_info(new base::DictionaryValue); |
| PopulateAppDict(app_data, app_info.get()); |
| apps_list->Append(app_info.release()); |
| } |
| settings.SetWithoutPathExpansion("apps", apps_list.release()); |
| |
| web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.setSettings", |
| settings); |
| } |
| |
| void KioskAppsHandler::HandleInitializeKioskAppSettings( |
| const base::ListValue* args) { |
| KioskAppManager::Get()->GetConsumerKioskModeStatus( |
| base::Bind(&KioskAppsHandler::OnGetConsumerKioskModeStatus, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void KioskAppsHandler::HandleGetKioskAppSettings(const base::ListValue* args) { |
| SendKioskAppSettings(); |
| } |
| |
| |
| void KioskAppsHandler::HandleAddKioskApp(const base::ListValue* args) { |
| if (!initialized_ || !is_kiosk_enabled_) |
| return; |
| |
| std::string input; |
| CHECK(args->GetString(0, &input)); |
| |
| std::string app_id; |
| if (!ExtractsAppIdFromInput(input, &app_id)) { |
| OnKioskAppDataLoadFailure(input); |
| return; |
| } |
| |
| kiosk_app_manager_->AddApp(app_id); |
| } |
| |
| void KioskAppsHandler::HandleRemoveKioskApp(const base::ListValue* args) { |
| if (!initialized_ || !is_kiosk_enabled_) |
| return; |
| |
| std::string app_id; |
| CHECK(args->GetString(0, &app_id)); |
| |
| kiosk_app_manager_->RemoveApp(app_id); |
| } |
| |
| void KioskAppsHandler::HandleEnableKioskAutoLaunch( |
| const base::ListValue* args) { |
| if (!initialized_ || !is_kiosk_enabled_) |
| return; |
| |
| std::string app_id; |
| CHECK(args->GetString(0, &app_id)); |
| |
| kiosk_app_manager_->SetAutoLaunchApp(app_id); |
| } |
| |
| void KioskAppsHandler::HandleDisableKioskAutoLaunch( |
| const base::ListValue* args) { |
| if (!initialized_ || !is_kiosk_enabled_) |
| return; |
| |
| std::string app_id; |
| CHECK(args->GetString(0, &app_id)); |
| |
| std::string startup_app_id = kiosk_app_manager_->GetAutoLaunchApp(); |
| if (startup_app_id != app_id) |
| return; |
| |
| kiosk_app_manager_->SetAutoLaunchApp(""); |
| } |
| |
| void KioskAppsHandler::HandleSetDisableBailoutShortcut( |
| const base::ListValue* args) { |
| if (!initialized_ || !is_kiosk_enabled_) |
| return; |
| |
| bool disable_bailout_shortcut; |
| CHECK(args->GetBoolean(0, &disable_bailout_shortcut)); |
| |
| CrosSettings::Get()->SetBoolean( |
| kAccountsPrefDeviceLocalAccountAutoLoginBailoutEnabled, |
| !disable_bailout_shortcut); |
| } |
| |
| } // namespace chromeos |