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