Represent kiosk apps as user pods instead of menu items.

Add a custom user pod icon for such apps.
Enable this UI by default.
Provide --disable-new-kiosk-ui flag which reverts back to the original UI (menu).

BUG=334304,341884
R=xiyuan@chromium.org
TBR=oshima

Review URL: https://codereview.chromium.org/158833003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251315 0039d316-1c4b-4281-b951-d872f2087c98
parent 71807856
......@@ -14173,6 +14173,9 @@ After you create a new supervised user, you can manage their settings at any tim
<message name="IDS_ADD_USER_BUTTON" desc="Text shown on an add user button on login/locker screen">
Add User
</message>
<message name="IDS_LAUNCH_APP_BUTTON" desc="Test shown on the button that launches kiosk app from Chrome OS login UI">
Launch App
</message>
<message name="IDS_SCREEN_LOCK_SIGN_OUT">
Sign out
</message>
......@@ -14187,6 +14190,9 @@ After you create a new supervised user, you can manage their settings at any tim
<message name="IDS_ADD_USER_BUTTON" desc="Text shown on an add user button on login/locker screen">
Add user
</message>
<message name="IDS_LAUNCH_APP_BUTTON" desc="Test shown on the button that launches kiosk app from Chrome OS login UI">
Launch app
</message>
<message name="IDS_SCREEN_LOCK_SIGN_OUT">
Sign out
</message>
......
......@@ -446,6 +446,7 @@
<structure type="chrome_scaled_image" name="IDR_LOGIN_GUEST" file="common/login_guest.png" />
<if expr="pp_ifdef('chromeos')">
<structure type="chrome_scaled_image" name="IDR_MANAGED_MODE_ICON" file="cros/managed_mode_icon.png" />
<structure type="chrome_scaled_image" name="IDR_KIOSK_APP_USER_POD_ICON" file="cros/kiosk_app_user_pod_icon.png" />
</if>
<structure type="chrome_scaled_image" name="IDR_MANAGED_USER_ICON" file="common/limited_user.png" />
<structure type="chrome_scaled_image" name="IDR_MANAGED_USER_LABEL_BOTTOM" file="common/managed_user_theme/label_bg_bottom.png" />
......
......@@ -82,6 +82,16 @@ const char kTestClientId[] = "fake-client-id";
const char kTestAppScope[] =
"https://www.googleapis.com/auth/userinfo.profile";
// Test JS API.
const char kLaunchAppForTestNewAPI[] =
"login.AccountPickerScreen.runAppForTesting";
const char kLaunchAppForTestOldAPI[] =
"login.AppsMenuButton.runAppForTesting";
const char kCheckDiagnosticModeNewAPI[] =
"$('oobe').confirmDiagnosticMode_";
const char kCheckDiagnosticModeOldAPI[] =
"$('show-apps-button').confirmDiagnosticMode_";
// Helper function for GetConsumerKioskAutoLaunchStatusCallback.
void ConsumerKioskAutoLaunchStatusCheck(
KioskAppManager::ConsumerKioskAutoLaunchStatus* out_status,
......@@ -299,6 +309,15 @@ class KioskTest : public OobeBaseTest {
return server_url.ReplaceComponents(replace_webstore_host);
}
void LaunchApp(const std::string& app_id, bool diagnostic_mode) {
bool new_kiosk_ui = !CommandLine::ForCurrentProcess()->
HasSwitch(switches::kDisableNewKioskUI);
GetLoginUI()->CallJavascriptFunction(new_kiosk_ui ?
kLaunchAppForTestNewAPI : kLaunchAppForTestOldAPI,
base::StringValue(app_id),
base::FundamentalValue(diagnostic_mode));
}
void ReloadKioskApps() {
KioskAppManager::Get()->AddApp(test_app_id_);
}
......@@ -336,9 +355,7 @@ class KioskTest : public OobeBaseTest {
if (!network_setup_cb.is_null())
network_setup_cb.Run();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
base::StringValue(test_app_id_));
LaunchApp(test_app_id(), false);
}
const extensions::Extension* GetInstalledApp() {
......@@ -583,21 +600,22 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchInDiagnosticMode) {
PrepareAppLaunch();
SimulateNetworkOnline();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
base::StringValue(kTestKioskApp),
base::FundamentalValue(true));
LaunchApp(kTestKioskApp, true);
content::WebContents* login_contents = GetLoginUI()->GetWebContents();
JsConditionWaiter(login_contents,
"$('show-apps-button').confirmDiagnosticMode_").Wait();
bool new_kiosk_ui = !CommandLine::ForCurrentProcess()->
HasSwitch(switches::kDisableNewKioskUI);
JsConditionWaiter(login_contents, new_kiosk_ui ?
kCheckDiagnosticModeNewAPI : kCheckDiagnosticModeOldAPI).Wait();
std::string diagnosticMode(new_kiosk_ui ?
kCheckDiagnosticModeNewAPI : kCheckDiagnosticModeOldAPI);
ASSERT_TRUE(content::ExecuteScript(
login_contents,
"(function() {"
"var e = new Event('click');"
"$('show-apps-button').confirmDiagnosticMode_."
"var e = new Event('click');" +
diagnosticMode + "."
"okButton_.dispatchEvent(e);"
"})();"));
......@@ -611,9 +629,7 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchOfflineEnabledAppNoNetwork) {
PrepareAppLaunch();
SimulateNetworkOffline();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
base::StringValue(test_app_id()));
LaunchApp(test_app_id(), false);
WaitForAppLaunchSuccess();
}
......@@ -630,9 +646,7 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchOfflineEnabledAppNoUpdate) {
PrepareAppLaunch();
SimulateNetworkOnline();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
base::StringValue(test_app_id()));
LaunchApp(test_app_id(), false);
WaitForAppLaunchSuccess();
EXPECT_EQ("1.0.0", GetInstalledAppVersion().GetString());
......@@ -651,9 +665,7 @@ IN_PROC_BROWSER_TEST_F(KioskTest, LaunchOfflineEnabledAppHasUpdate) {
PrepareAppLaunch();
SimulateNetworkOnline();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
base::StringValue(test_app_id()));
LaunchApp(test_app_id(), false);
WaitForAppLaunchSuccess();
EXPECT_EQ("2.0.0", GetInstalledAppVersion().GetString());
......@@ -977,9 +989,7 @@ IN_PROC_BROWSER_TEST_F(KioskEnterpriseTest, EnterpriseKioskApp) {
base::Unretained(KioskAppManager::Get()),
kTestEnterpriseKioskApp, &app)).Wait();
GetLoginUI()->CallJavascriptFunction(
"login.AppsMenuButton.runAppForTesting",
base::StringValue(kTestEnterpriseKioskApp));
LaunchApp(kTestEnterpriseKioskApp, false);
// Wait for the Kiosk App to launch.
content::WindowedNotificationObserver(
......
......@@ -139,6 +139,10 @@ cr.define('cr.ui.login', function() {
document.documentElement.setAttribute('screen', displayType);
},
get newKioskUI() {
return loadTimeData.getString('newKioskUI') == 'on';
},
/**
* Returns dimensions of screen exluding header bar.
* @type {Object}
......
......@@ -46,8 +46,12 @@ cr.define('login', function() {
$('cancel-multiple-sign-in-button').addEventListener('click',
this.handleCancelMultipleSignInClick_);
if (Oobe.getInstance().displayType == DISPLAY_TYPE.LOGIN ||
Oobe.getInstance().displayType == DISPLAY_TYPE.OOBE)
login.AppsMenuButton.decorate($('show-apps-button'));
Oobe.getInstance().displayType == DISPLAY_TYPE.OOBE) {
if (Oobe.getInstance().newKioskUI)
chrome.send('initializeKioskApps');
else
login.AppsMenuButton.decorate($('show-apps-button'));
}
this.updateUI_();
},
......@@ -230,8 +234,10 @@ cr.define('login', function() {
(!gaiaIsActive && !accountPickerIsActive);
$('cancel-multiple-sign-in-item').hidden = !isMultiProfilesUI;
if (!$('apps-header-bar-item').hidden)
$('show-apps-button').didShow();
if (!Oobe.getInstance().newKioskUI) {
if (!$('apps-header-bar-item').hidden)
$('show-apps-button').didShow();
}
},
/**
......
......@@ -23,6 +23,9 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
return {
EXTERNAL_API: [
'loadUsers',
'runAppForTesting',
'setApps',
'showAppError',
'updateUserImage',
'forceOnlineSignin',
'setCapsLockState',
......@@ -181,6 +184,39 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
}
},
/**
* Runs app with a given id from the list of loaded apps.
* @param {!string} app_id of an app to run.
* @param {boolean=} opt_diagnostic_mode Whether to run the app in
* diagnostic mode. Default is false.
*/
runAppForTesting: function(app_id, opt_diagnostic_mode) {
$('pod-row').findAndRunAppForTesting(app_id, opt_diagnostic_mode);
},
/**
* Adds given apps to the pod row.
* @param {array} apps Array of apps.
*/
setApps: function(apps) {
$('pod-row').setApps(apps);
},
/**
* Shows the given kiosk app error message.
* @param {!string} message Error message to show.
*/
showAppError: function(message) {
// TODO(nkostylev): Figure out a way to show kiosk app launch error
// pointing to the kiosk app pod.
/** @const */ var BUBBLE_PADDING = 12;
$('bubble').showTextForElement($('pod-row'),
message,
cr.ui.Bubble.Attachment.BOTTOM,
$('pod-row').offsetWidth / 2,
BUBBLE_PADDING);
},
/**
* Updates current image of a user.
* @param {string} username User for which to update the image.
......
......@@ -174,7 +174,8 @@ button.custom-button:focus:hover {
display: -webkit-box;
}
.pod .signin-button {
.pod .signin-button,
.pod .launch-app-button {
box-sizing: border-box;
display: inline-block;
height: 26px;
......@@ -184,7 +185,8 @@ button.custom-button:focus:hover {
padding: 4px 8px;
}
.pod:not(.focused) .signin-button {
.pod:not(.focused) .signin-button,
.pod:not(.focused) .launch-app-button {
display: none;
}
......@@ -280,6 +282,10 @@ html[dir=rtl] .user-type-icon-area {
background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY');
}
.user-type-icon-area.app .user-type-icon-image {
background-image: url('chrome://theme/IDR_KIOSK_APP_USER_POD_ICON');
}
.user-type-icon-area.policy:hover ~ .user-type-bubble {
opacity: 1;
visibility: visible;
......
......@@ -15,6 +15,8 @@
</button>
</div>
<button class="signin-button" i18n-content="signinButton"></button>
<button class="launch-app-button" i18n-content="launchAppButton" hidden>
</button>
<div class="locked-indicator" hidden></div>
</div>
<div class="action-box-area">
......
......@@ -22,8 +22,19 @@
namespace chromeos {
namespace {
// JS functions that define new and old kiosk UI API.
const char kKioskSetAppsNewAPI[] = "login.AccountPickerScreen.setApps";
const char kKioskSetAppsOldAPI[] = "login.AppsMenuButton.setApps";
const char kKioskShowErrorNewAPI[] = "login.AccountPickerScreen.showAppError";
const char kKioskShowErrorOldAPI[] = "login.AppsMenuButton.showError";
} // namespace
KioskAppMenuHandler::KioskAppMenuHandler()
: weak_ptr_factory_(this) {
: weak_ptr_factory_(this),
is_webui_initialized_(false) {
KioskAppManager::Get()->AddObserver(this);
}
......@@ -60,6 +71,9 @@ void KioskAppMenuHandler::RegisterMessages() {
}
void KioskAppMenuHandler::SendKioskApps() {
if (!is_webui_initialized_)
return;
KioskAppManager::Apps apps;
KioskAppManager::Get()->GetApps(&apps);
......@@ -68,6 +82,7 @@ void KioskAppMenuHandler::SendKioskApps() {
const KioskAppManager::App& app_data = apps[i];
scoped_ptr<base::DictionaryValue> app_info(new base::DictionaryValue);
app_info->SetBoolean("isApp", true);
app_info->SetString("id", app_data.app_id);
app_info->SetString("label", app_data.name);
......@@ -80,12 +95,16 @@ void KioskAppMenuHandler::SendKioskApps() {
apps_list.Append(app_info.release());
}
web_ui()->CallJavascriptFunction("login.AppsMenuButton.setApps",
apps_list);
bool new_kiosk_ui = !CommandLine::ForCurrentProcess()->
HasSwitch(switches::kDisableNewKioskUI);
web_ui()->CallJavascriptFunction(new_kiosk_ui ?
kKioskSetAppsNewAPI : kKioskSetAppsOldAPI,
apps_list);
}
void KioskAppMenuHandler::HandleInitializeKioskApps(
const base::ListValue* args) {
is_webui_initialized_ = true;
SendKioskApps();
}
......@@ -105,8 +124,11 @@ void KioskAppMenuHandler::HandleCheckKioskAppLaunchError(
KioskAppLaunchError::Clear();
const std::string error_message = KioskAppLaunchError::GetErrorMessage(error);
web_ui()->CallJavascriptFunction("login.AppsMenuButton.showError",
base::StringValue(error_message));
bool new_kiosk_ui = !CommandLine::ForCurrentProcess()->
HasSwitch(switches::kDisableNewKioskUI);
web_ui()->CallJavascriptFunction(new_kiosk_ui ?
kKioskShowErrorNewAPI : kKioskShowErrorOldAPI,
base::StringValue(error_message));
}
void KioskAppMenuHandler::OnKioskAppsSettingsChanged() {
......
......@@ -45,6 +45,9 @@ class KioskAppMenuHandler : public content::WebUIMessageHandler,
base::WeakPtrFactory<KioskAppMenuHandler> weak_ptr_factory_;
// True when WebUI is initialized. Otherwise don't allow calling JS functions.
bool is_webui_initialized_;
DISALLOW_COPY_AND_ASSIGN(KioskAppMenuHandler);
};
......
......@@ -378,6 +378,10 @@ void OobeUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) {
system::keyboard_settings::ForceKeyboardDrivenUINavigation();
localized_strings->SetString("highlightStrength",
keyboard_driven_oobe ? "strong" : "normal");
bool new_kiosk_ui = !CommandLine::ForCurrentProcess()->
HasSwitch(switches::kDisableNewKioskUI);
localized_strings->SetString("newKioskUI", new_kiosk_ui ? "on" : "off");
}
void OobeUI::InitializeScreenMaps() {
......
......@@ -331,6 +331,7 @@ void SigninScreenHandler::DeclareLocalizedValues(
IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME);
builder->Add("signedIn", IDS_SCREEN_LOCK_ACTIVE_USER);
builder->Add("signinButton", IDS_LOGIN_BUTTON);
builder->Add("launchAppButton", IDS_LAUNCH_APP_BUTTON);
builder->Add("shutDown", IDS_SHUTDOWN_BUTTON);
builder->Add("addUser", IDS_ADD_USER_BUTTON);
builder->Add("browseAsGuest", IDS_GO_INCOGNITO_BUTTON);
......
......@@ -56,6 +56,9 @@ const char kDisableLoginAnimations[] = "disable-login-animations";
// Disable new channel switcher UI.
const char kDisableNewChannelSwitcherUI[] = "disable-new-channel-switcher-ui";
// Disables new Kiosk UI when kiosk apps are represented as user pods.
const char kDisableNewKioskUI[] = "disable-new-kiosk-ui";
// Disable Quickoffice component app thus handlers won't be registered so
// it will be possible to install another version as normal app for testing.
const char kDisableQuickofficeComponentApp[] =
......
......@@ -35,6 +35,7 @@ CHROMEOS_EXPORT extern const char kDisableIMEModeIndicator[];
CHROMEOS_EXPORT extern const char kDisableLocalAccounts[];
CHROMEOS_EXPORT extern const char kDisableLoginAnimations[];
CHROMEOS_EXPORT extern const char kDisableNewChannelSwitcherUI[];
CHROMEOS_EXPORT extern const char kDisableNewKioskUI[];
CHROMEOS_EXPORT extern const char kDisableOOBEBlockingUpdate[];
CHROMEOS_EXPORT extern const char kDisableOnlineEULA[];
CHROMEOS_EXPORT extern const char kDisableOobeAnimation[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment