blob: f6ee3f22aa31607be7d8391edd6beace191fee96 [file] [log] [blame]
// Copyright (c) 2012 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 <string>
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/system/tray/system_tray.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/login_manager_test.h"
#include "chrome/browser/chromeos/login/login_wizard.h"
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/test/js_checker.h"
#include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_auth_policy_client.h"
#include "chromeos/settings/cros_settings_names.h"
#include "components/signin/core/account_id/account_id.h"
#include "components/user_manager/user_names.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/browser/extension_system.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/test/rect_test_util.h"
using ::gfx::test::RectContains;
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;
namespace chromeos {
namespace {
const char kGaiaId[] = "12345";
const char kTestUser[] = "test-user@gmail.com";
const char kPassword[] = "password";
class LoginUserTest : public InProcessBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitchASCII(switches::kLoginUser, "TestUser@gmail.com");
command_line->AppendSwitchASCII(switches::kLoginProfile, "hash");
}
};
class LoginGuestTest : public InProcessBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kGuestSession);
command_line->AppendSwitch(::switches::kIncognito);
command_line->AppendSwitchASCII(switches::kLoginProfile, "hash");
command_line->AppendSwitchASCII(
switches::kLoginUser, user_manager::GuestAccountId().GetUserEmail());
}
};
class LoginCursorTest : public InProcessBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kLoginManager);
}
};
class LoginSigninTest : public InProcessBrowserTest {
protected:
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kLoginManager);
command_line->AppendSwitch(switches::kForceLoginManagerInTests);
}
void SetUpOnMainThread() override {
LoginDisplayHostWebUI::DisableRestrictiveProxyCheckForTest();
}
};
class LoginTest : public LoginManagerTest {
public:
LoginTest() : LoginManagerTest(true) {}
~LoginTest() override {}
void StartGaiaAuthOffline() {
content::DOMMessageQueue message_queue;
// clang-format off
const std::string js = "(function() {"
"var authenticator = $('gaia-signin').gaiaAuthHost_;"
"authenticator.addEventListener('ready',"
"function f() {"
"authenticator.removeEventListener('ready', f);"
"window.domAutomationController.send('offlineLoaded');"
"});"
"$('error-offline-login-link').onclick();"
"})();";
// clang-format on
ASSERT_TRUE(content::ExecuteScript(web_contents(), js));
std::string message;
do {
ASSERT_TRUE(message_queue.WaitForMessage(&message));
} while (message != "\"offlineLoaded\"");
}
void SubmitGaiaAuthOfflineForm(const std::string& user_email,
const std::string& password) {
const std::string animated_pages =
"document.querySelector('#offline-gaia /deep/ "
"#animatedPages')";
const std::string email_input =
"document.querySelector('#offline-gaia /deep/ #emailInput')";
const std::string email_next_button =
"document.querySelector('#offline-gaia /deep/ #emailSection "
"/deep/ #button')";
const std::string password_input =
"document.querySelector('#offline-gaia /deep/ "
"#passwordInput')";
const std::string password_next_button =
"document.querySelector('#offline-gaia /deep/ #passwordSection"
" /deep/ #button')";
content::DOMMessageQueue message_queue;
JSExpect("!document.querySelector('#offline-gaia').hidden");
JSExpect("document.querySelector('#signin-frame').hidden");
const std::string js =
animated_pages +
".addEventListener('neon-animation-finish',"
"function() {"
"window.domAutomationController.send('switchToPassword');"
"})";
ASSERT_TRUE(content::ExecuteScript(web_contents(), js));
std::string set_email = email_input + ".value = '$Email'";
base::ReplaceSubstringsAfterOffset(&set_email, 0, "$Email", user_email);
ASSERT_TRUE(content::ExecuteScript(web_contents(), set_email));
ASSERT_TRUE(content::ExecuteScript(web_contents(),
email_next_button + ".fire('tap')"));
std::string message;
do {
ASSERT_TRUE(message_queue.WaitForMessage(&message));
} while (message != "\"switchToPassword\"");
std::string set_password = password_input + ".value = '$Password'";
base::ReplaceSubstringsAfterOffset(&set_password, 0, "$Password", password);
ASSERT_TRUE(content::ExecuteScript(web_contents(), set_password));
ASSERT_TRUE(content::ExecuteScript(web_contents(),
password_next_button + ".fire('tap')"));
}
void PrepareOfflineLogin() {
bool show_user;
ASSERT_TRUE(CrosSettings::Get()->GetBoolean(
kAccountsPrefShowUserNamesOnSignIn, &show_user));
ASSERT_FALSE(show_user);
StartGaiaAuthOffline();
UserContext user_context(
AccountId::FromUserEmailGaiaId(kTestUser, kGaiaId));
user_context.SetKey(Key(kPassword));
SetExpectedCredentials(user_context);
}
};
// Used to make sure that the system tray is visible and within the screen
// bounds after login.
void TestSystemTrayIsVisible(bool otr) {
ash::SystemTray* tray = ash::Shell::Get()->GetPrimarySystemTray();
aura::Window* primary_win = ash::Shell::GetPrimaryRootWindow();
ash::Shelf* shelf = ash::Shelf::ForWindow(primary_win);
SCOPED_TRACE(testing::Message()
<< "ShelfVisibilityState=" << shelf->GetVisibilityState()
<< " ShelfAutoHideBehavior=" << shelf->auto_hide_behavior());
EXPECT_TRUE(tray->visible());
// This check flakes for LoginGuestTest: https://crbug.com/693106.
if (!otr)
EXPECT_TRUE(RectContains(primary_win->bounds(), tray->GetBoundsInScreen()));
}
} // namespace
// After a chrome crash, the session manager will restart chrome with
// the -login-user flag indicating that the user is already logged in.
// This profile should NOT be an OTR profile.
IN_PROC_BROWSER_TEST_F(LoginUserTest, UserPassed) {
Profile* profile = browser()->profile();
std::string profile_base_path("hash");
profile_base_path.insert(0, chrome::kProfileDirPrefix);
EXPECT_EQ(profile_base_path, profile->GetPath().BaseName().value());
EXPECT_FALSE(profile->IsOffTheRecord());
TestSystemTrayIsVisible(false);
}
// After a guest login, we should get the OTR default profile.
IN_PROC_BROWSER_TEST_F(LoginGuestTest, GuestIsOTR) {
Profile* profile = browser()->profile();
EXPECT_TRUE(profile->IsOffTheRecord());
// Ensure there's extension service for this profile.
EXPECT_TRUE(extensions::ExtensionSystem::Get(profile)->extension_service());
TestSystemTrayIsVisible(true);
}
// Verifies the cursor is hidden at startup on login screen.
IN_PROC_BROWSER_TEST_F(LoginCursorTest, CursorHidden) {
// Login screen needs to be shown explicitly when running test.
ShowLoginWizard(OobeScreen::SCREEN_SPECIAL_LOGIN);
// Cursor should be hidden at startup
EXPECT_FALSE(ash::Shell::Get()->cursor_manager()->IsCursorVisible());
// Cursor should be shown after cursor is moved.
EXPECT_TRUE(ui_test_utils::SendMouseMoveSync(gfx::Point()));
EXPECT_TRUE(ash::Shell::Get()->cursor_manager()->IsCursorVisible());
TestSystemTrayIsVisible(false);
}
// Verifies that the webui for login comes up successfully.
IN_PROC_BROWSER_TEST_F(LoginSigninTest, WebUIVisible) {
content::WindowedNotificationObserver(
chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
content::NotificationService::AllSources())
.Wait();
}
IN_PROC_BROWSER_TEST_F(LoginTest, PRE_GaiaAuthOffline) {
RegisterUser(AccountId::FromUserEmailGaiaId(kTestUser, kGaiaId));
StartupUtils::MarkOobeCompleted();
CrosSettings::Get()->SetBoolean(kAccountsPrefShowUserNamesOnSignIn, false);
}
// Flaky, see http://crbug/692364.
IN_PROC_BROWSER_TEST_F(LoginTest, DISABLED_GaiaAuthOffline) {
PrepareOfflineLogin();
content::WindowedNotificationObserver session_start_waiter(
chrome::NOTIFICATION_SESSION_STARTED,
content::NotificationService::AllSources());
SubmitGaiaAuthOfflineForm(kTestUser, kPassword);
session_start_waiter.Wait();
TestSystemTrayIsVisible(false);
}
} // namespace chromeos