1 // Copyright 2014 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/chromeos/login/test/oobe_base_test.h"
6
7 #include "ash/public/cpp/ash_switches.h"
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/location.h"
11 #include "base/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/threading/thread_task_runner_handle.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browser_process_platform_part.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
18 #include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
19 #include "chrome/browser/chromeos/login/test/https_forwarder.h"
20 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
21 #include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
22 #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
23 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
24 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
25 #include "chrome/browser/lifetime/application_lifetime.h"
26 #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
27 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
28 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
29 #include "chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h"
30 #include "chrome/browser/ui/webui/signin/signin_utils.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chromeos/constants/chromeos_features.h"
33 #include "chromeos/constants/chromeos_switches.h"
34 #include "chromeos/dbus/dbus_thread_manager.h"
35 #include "chromeos/dbus/fake_update_engine_client.h"
36 #include "chromeos/dbus/shill/fake_shill_manager_client.h"
37 #include "components/policy/core/common/policy_switches.h"
38 #include "components/user_manager/fake_user_manager.h"
39 #include "content/public/browser/notification_observer.h"
40 #include "content/public/browser/notification_registrar.h"
41 #include "content/public/browser/notification_service.h"
42 #include "content/public/test/browser_test_utils.h"
43 #include "content/public/test/test_utils.h"
44 #include "google_apis/gaia/gaia_switches.h"
45 #include "net/dns/mock_host_resolver.h"
46
47 namespace chromeos {
48
49 namespace {
50
51 class GaiaPageEventWaiter : public test::TestConditionWaiter {
52 public:
GaiaPageEventWaiter(const std::string & authenticator_id,const std::string & event)53 GaiaPageEventWaiter(const std::string& authenticator_id,
54 const std::string& event) {
55 std::string js =
56 R"((function() {
57 var authenticator = $AuthenticatorId;
58 var f = function() {
59 authenticator.removeEventListener('$Event', f);
60 window.domAutomationController.send('Done');
61 };
62 authenticator.addEventListener('$Event', f);
63 })();)";
64 base::ReplaceSubstringsAfterOffset(&js, 0, "$AuthenticatorId",
65 authenticator_id);
66 base::ReplaceSubstringsAfterOffset(&js, 0, "$Event", event);
67 test::OobeJS().Evaluate(js);
68 }
69
~GaiaPageEventWaiter()70 ~GaiaPageEventWaiter() override { EXPECT_TRUE(wait_called_); }
71
72 // test::TestConditionWaiter:
Wait()73 void Wait() override {
74 ASSERT_FALSE(wait_called_) << "Wait should be called once";
75 wait_called_ = true;
76 std::string message;
77 do {
78 ASSERT_TRUE(message_queue.WaitForMessage(&message));
79 } while (message != "\"Done\"");
80 }
81
82 private:
83 content::DOMMessageQueue message_queue;
84 bool wait_called_ = false;
85 };
86
87 } // namespace
88
OobeBaseTest()89 OobeBaseTest::OobeBaseTest() {
90 set_exit_when_last_browser_closes(false);
91 }
92
~OobeBaseTest()93 OobeBaseTest::~OobeBaseTest() {}
94
RegisterAdditionalRequestHandlers()95 void OobeBaseTest::RegisterAdditionalRequestHandlers() {}
96
SetUp()97 void OobeBaseTest::SetUp() {
98 RegisterAdditionalRequestHandlers();
99 MixinBasedInProcessBrowserTest::SetUp();
100 }
101
SetUpCommandLine(base::CommandLine * command_line)102 void OobeBaseTest::SetUpCommandLine(base::CommandLine* command_line) {
103 command_line->AppendSwitch(chromeos::switches::kLoginManager);
104 command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
105 if (!needs_background_networking_)
106 command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
107 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
108
109 MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line);
110 }
111
CreatedBrowserMainParts(content::BrowserMainParts * browser_main_parts)112 void OobeBaseTest::CreatedBrowserMainParts(
113 content::BrowserMainParts* browser_main_parts) {
114 // If the test initially shows views login screen, this notification might
115 // come before SetUpOnMainThread(), so the observer has to be set up early.
116 login_screen_load_observer_.reset(new content::WindowedNotificationObserver(
117 chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
118 content::NotificationService::AllSources()));
119
120 MixinBasedInProcessBrowserTest::CreatedBrowserMainParts(browser_main_parts);
121 }
122
SetUpInProcessBrowserTestFixture()123 void OobeBaseTest::SetUpInProcessBrowserTestFixture() {
124 MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
125
126 // UpdateEngineClientStubImpl have logic that simulates state changes
127 // based on timer. It is nice simulation for chromeos-on-linux, but
128 // may lead to flakiness in debug/*SAN tests.
129 // Set up FakeUpdateEngineClient that does not have any timer-based logic.
130 std::unique_ptr<DBusThreadManagerSetter> dbus_setter =
131 chromeos::DBusThreadManager::GetSetterForTesting();
132 update_engine_client_ = new FakeUpdateEngineClient;
133 dbus_setter->SetUpdateEngineClient(
134 std::unique_ptr<UpdateEngineClient>(update_engine_client_));
135 }
136
SetUpOnMainThread()137 void OobeBaseTest::SetUpOnMainThread() {
138 ShillManagerClient::Get()->GetTestInterface()->SetupDefaultEnvironment();
139
140 host_resolver()->AddRule("*", "127.0.0.1");
141
142 test::UserSessionManagerTestApi session_manager_test_api(
143 UserSessionManager::GetInstance());
144 session_manager_test_api.SetShouldObtainTokenHandleInTests(false);
145
146 LoginDisplayHostWebUI::DisableRestrictiveProxyCheckForTest();
147
148 if (ShouldWaitForOobeUI()) {
149 WaitForOobeUI();
150 }
151 MixinBasedInProcessBrowserTest::SetUpOnMainThread();
152 }
153
ShouldWaitForOobeUI()154 bool OobeBaseTest::ShouldWaitForOobeUI() {
155 return true;
156 }
157
GetLoginUI()158 content::WebUI* OobeBaseTest::GetLoginUI() {
159 return LoginDisplayHost::default_host()->GetOobeUI()->web_ui();
160 }
161
WaitForOobeUI()162 void OobeBaseTest::WaitForOobeUI() {
163 // Wait for notification first. Otherwise LoginDisplayHost might not be
164 // created yet.
165 MaybeWaitForLoginScreenLoad();
166
167 // Wait for OobeUI to finish loading.
168 base::RunLoop run_loop;
169 if (!LoginDisplayHost::default_host()->GetOobeUI()->IsJSReady(
170 run_loop.QuitClosure())) {
171 run_loop.Run();
172 }
173 }
174
WaitForGaiaPageLoad()175 void OobeBaseTest::WaitForGaiaPageLoad() {
176 WaitForSigninScreen();
177 WaitForGaiaPageReload();
178 }
179
WaitForGaiaPageLoadAndPropertyUpdate()180 void OobeBaseTest::WaitForGaiaPageLoadAndPropertyUpdate() {
181 // Some tests need to checks properties such as back button visibility and
182 // #identifier in the gaia location, which are modified after the gaia page
183 // 'ready' event arrives. To ensure that these properties are updated before
184 // they are checked, use WaitForGaiaPageBackButtonUpdate() instead of
185 // WaitForGaiaPageLoad().
186 WaitForSigninScreen();
187 WaitForGaiaPageBackButtonUpdate();
188 }
189
WaitForGaiaPageReload()190 void OobeBaseTest::WaitForGaiaPageReload() {
191 CreateGaiaPageEventWaiter("ready")->Wait();
192 }
193
WaitForGaiaPageBackButtonUpdate()194 void OobeBaseTest::WaitForGaiaPageBackButtonUpdate() {
195 CreateGaiaPageEventWaiter("backButton")->Wait();
196 }
197
198 std::unique_ptr<test::TestConditionWaiter>
CreateGaiaPageEventWaiter(const std::string & event)199 OobeBaseTest::CreateGaiaPageEventWaiter(const std::string& event) {
200 return std::make_unique<GaiaPageEventWaiter>(authenticator_id_, event);
201 }
202
WaitForSigninScreen()203 void OobeBaseTest::WaitForSigninScreen() {
204 WizardController* wizard_controller = WizardController::default_controller();
205 if (wizard_controller && wizard_controller->is_initialized())
206 wizard_controller->SkipToLoginForTesting();
207
208 WizardController::SkipPostLoginScreensForTesting();
209
210 MaybeWaitForLoginScreenLoad();
211 }
CheckJsExceptionErrors(int number)212 void OobeBaseTest::CheckJsExceptionErrors(int number) {
213 test::OobeJS().ExpectEQ("cr.ErrorStore.getInstance().length", number);
214 }
215
SigninFrameJS()216 test::JSChecker OobeBaseTest::SigninFrameJS() {
217 content::RenderFrameHost* frame = signin::GetAuthFrame(
218 LoginDisplayHost::default_host()->GetOobeWebContents(),
219 gaia_frame_parent_);
220 test::JSChecker result = test::JSChecker(frame);
221 return result;
222 }
223
224 // static
GetFirstSigninScreen()225 OobeScreenId OobeBaseTest::GetFirstSigninScreen() {
226 bool childSpecificSigninEnabled = features::IsChildSpecificSigninEnabled() &&
227 !g_browser_process->platform_part()
228 ->browser_policy_connector_chromeos()
229 ->IsEnterpriseManaged();
230 return childSpecificSigninEnabled ? UserCreationView::kScreenId
231 : GaiaView::kScreenId;
232 }
233
MaybeWaitForLoginScreenLoad()234 void OobeBaseTest::MaybeWaitForLoginScreenLoad() {
235 if (!login_screen_load_observer_)
236 return;
237 login_screen_load_observer_->Wait();
238 login_screen_load_observer_.reset();
239 }
240
241 } // namespace chromeos
242