1 // Copyright 2020 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/screens/terms_of_service_screen.h"
6 
7 #include "ash/public/cpp/login_screen_test_api.h"
8 #include "base/bind.h"
9 #include "base/run_loop.h"
10 #include "chrome/browser/chromeos/login/existing_user_controller.h"
11 #include "chrome/browser/chromeos/login/screen_manager.h"
12 #include "chrome/browser/chromeos/login/test/device_state_mixin.h"
13 #include "chrome/browser/chromeos/login/test/embedded_test_server_mixin.h"
14 #include "chrome/browser/chromeos/login/test/js_checker.h"
15 #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h"
16 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
17 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
18 #include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h"
19 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
20 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
21 #include "chrome/browser/chromeos/login/wizard_controller.h"
22 #include "chrome/browser/chromeos/policy/device_local_account.h"
23 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
24 #include "chrome/browser/chromeos/policy/device_policy_builder.h"
25 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
28 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
29 #include "chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h"
30 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
31 #include "components/policy/proto/chrome_device_policy.pb.h"
32 #include "content/public/test/browser_test.h"
33 #include "net/test/embedded_test_server/http_request.h"
34 #include "net/test/embedded_test_server/http_response.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 
37 namespace em = enterprise_management;
38 
39 using net::test_server::BasicHttpResponse;
40 using net::test_server::HttpRequest;
41 using net::test_server::HttpResponse;
42 
43 using testing::_;
44 using testing::InvokeWithoutArgs;
45 
46 namespace chromeos {
47 namespace {
48 
49 const char kAccountId[] = "dla@example.com";
50 const char kDisplayName[] = "display name";
51 
52 }  // namespace
53 
54 class TermsOfServiceScreenTest : public OobeBaseTest {
55  public:
TermsOfServiceScreenTest()56   TermsOfServiceScreenTest() {}
57   ~TermsOfServiceScreenTest() override = default;
58 
RegisterAdditionalRequestHandlers()59   void RegisterAdditionalRequestHandlers() override {
60     embedded_test_server()->RegisterRequestHandler(base::BindRepeating(
61         &TermsOfServiceScreenTest::HandleRequest, base::Unretained(this)));
62   }
63 
SetUpInProcessBrowserTestFixture()64   void SetUpInProcessBrowserTestFixture() override {
65     OobeBaseTest::SetUpInProcessBrowserTestFixture();
66     chromeos::SessionManagerClient::InitializeFakeInMemory();
67     InitializePolicy();
68   }
69 
InitializePolicy()70   void InitializePolicy() {
71     device_policy()->policy_data().set_public_key_version(1);
72     policy::DeviceLocalAccountTestHelper::SetupDeviceLocalAccount(
73         &device_local_account_policy_, kAccountId, kDisplayName);
74     UploadDeviceLocalAccountPolicy();
75   }
76 
BuildDeviceLocalAccountPolicy()77   void BuildDeviceLocalAccountPolicy() {
78     device_local_account_policy_.SetDefaultSigningKey();
79     device_local_account_policy_.Build();
80   }
81 
UploadDeviceLocalAccountPolicy()82   void UploadDeviceLocalAccountPolicy() {
83     BuildDeviceLocalAccountPolicy();
84     ASSERT_TRUE(local_policy_mixin_.server()->UpdatePolicy(
85         policy::dm_protocol::kChromePublicAccountPolicyType, kAccountId,
86         device_local_account_policy_.payload().SerializeAsString()));
87   }
88 
UploadAndInstallDeviceLocalAccountPolicy()89   void UploadAndInstallDeviceLocalAccountPolicy() {
90     UploadDeviceLocalAccountPolicy();
91     session_manager_client()->set_device_local_account_policy(
92         kAccountId, device_local_account_policy_.GetBlob());
93   }
94 
AddPublicSessionToDevicePolicy()95   void AddPublicSessionToDevicePolicy() {
96     em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
97     policy::DeviceLocalAccountTestHelper::AddPublicSession(&proto, kAccountId);
98     RefreshDevicePolicy();
99     ASSERT_TRUE(local_policy_mixin_.UpdateDevicePolicy(proto));
100   }
101 
WaitForDisplayName()102   void WaitForDisplayName() {
103     policy::DictionaryLocalStateValueWaiter("UserDisplayName", kDisplayName,
104                                             account_id_.GetUserEmail())
105         .Wait();
106   }
107 
WaitForPolicy()108   void WaitForPolicy() {
109     // Wait for the display name becoming available as that indicates
110     // device-local account policy is fully loaded, which is a prerequisite for
111     // successful login.
112     WaitForDisplayName();
113   }
114 
StartLogin()115   void StartLogin() {
116     ASSERT_TRUE(ash::LoginScreenTestApi::ExpandPublicSessionPod(account_id_));
117     ash::LoginScreenTestApi::ClickPublicExpandedSubmitButton();
118   }
119 
StartPublicSession()120   void StartPublicSession() {
121     UploadAndInstallDeviceLocalAccountPolicy();
122     AddPublicSessionToDevicePolicy();
123     WaitForPolicy();
124     StartLogin();
125   }
126 
SetUpTermsOfServiceUrlPolicy()127   void SetUpTermsOfServiceUrlPolicy() {
128     device_local_account_policy_.payload()
129         .mutable_termsofserviceurl()
130         ->set_value(TestServerBaseUrl());
131   }
132 
SetUpExitCallback()133   void SetUpExitCallback() {
134     TermsOfServiceScreen* screen = static_cast<TermsOfServiceScreen*>(
135         WizardController::default_controller()->screen_manager()->GetScreen(
136             TermsOfServiceScreenView::kScreenId));
137     original_callback_ = screen->get_exit_callback_for_testing();
138     screen->set_exit_callback_for_testing(base::BindRepeating(
139         &TermsOfServiceScreenTest::HandleScreenExit, base::Unretained(this)));
140   }
141 
WaitFosScreenShown()142   void WaitFosScreenShown() {
143     OobeScreenWaiter(TermsOfServiceScreenView::kScreenId).Wait();
144     EXPECT_TRUE(ash::LoginScreenTestApi::IsOobeDialogVisible());
145   }
146 
WaitForScreenExit()147   void WaitForScreenExit() {
148     if (screen_exited_)
149       return;
150     base::RunLoop run_loop;
151     screen_exit_callback_ = run_loop.QuitClosure();
152     run_loop.Run();
153   }
154 
TestServerBaseUrl()155   std::string TestServerBaseUrl() {
156     return base::TrimString(
157                embedded_test_server()->base_url().GetOrigin().spec(), "/",
158                base::TrimPositions::TRIM_TRAILING)
159         .as_string();
160   }
161 
HandleRequest(const HttpRequest & request)162   std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
163     std::string text = "By using this test you are agree to fix future bugs";
164     return BuildHttpResponse(text);
165   }
166 
167   // Returns a successful `BasicHttpResponse` with `content`.
BuildHttpResponse(const std::string & content)168   std::unique_ptr<BasicHttpResponse> BuildHttpResponse(
169       const std::string& content) {
170     std::unique_ptr<BasicHttpResponse> http_response =
171         std::make_unique<BasicHttpResponse>();
172     http_response->set_code(net::HTTP_OK);
173     http_response->set_content_type("text/plain");
174     http_response->set_content(content);
175     return http_response;
176   }
177 
session_manager_client()178   chromeos::FakeSessionManagerClient* session_manager_client() {
179     return chromeos::FakeSessionManagerClient::Get();
180   }
181 
182   base::Optional<TermsOfServiceScreen::Result> result_;
183   base::HistogramTester histogram_tester_;
184 
185  private:
RefreshDevicePolicy()186   void RefreshDevicePolicy() { policy_helper()->RefreshDevicePolicy(); }
187 
device_policy()188   policy::DevicePolicyBuilder* device_policy() {
189     return policy_helper()->device_policy();
190   }
191 
policy_helper()192   policy::DevicePolicyCrosTestHelper* policy_helper() {
193     return &policy_helper_;
194   }
195 
HandleScreenExit(TermsOfServiceScreen::Result result)196   void HandleScreenExit(TermsOfServiceScreen::Result result) {
197     screen_exited_ = true;
198     result_ = result;
199     original_callback_.Run(result);
200     if (screen_exit_callback_)
201       screen_exit_callback_.Run();
202   }
203 
204   bool screen_exited_ = false;
205   base::RepeatingClosure screen_exit_callback_;
206   TermsOfServiceScreen::ScreenExitCallback original_callback_;
207   policy::UserPolicyBuilder device_local_account_policy_;
208 
209   const AccountId account_id_ =
210       AccountId::FromUserEmail(GenerateDeviceLocalAccountUserId(
211           kAccountId,
212           policy::DeviceLocalAccount::TYPE_PUBLIC_SESSION));
213   policy::DevicePolicyCrosTestHelper policy_helper_;
214   chromeos::LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_};
215   chromeos::DeviceStateMixin device_state_{
216       &mixin_host_,
217       chromeos::DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED};
218 };
219 
IN_PROC_BROWSER_TEST_F(TermsOfServiceScreenTest,Skipped)220 IN_PROC_BROWSER_TEST_F(TermsOfServiceScreenTest, Skipped) {
221   StartPublicSession();
222 
223   chromeos::test::WaitForPrimaryUserSessionStart();
224 
225   histogram_tester_.ExpectTotalCount(
226       "OOBE.StepCompletionTimeByExitReason.Terms-of-service.Accepted", 0);
227   histogram_tester_.ExpectTotalCount(
228       "OOBE.StepCompletionTimeByExitReason.Terms-of-service.Declined", 0);
229   histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Tos", 0);
230 }
231 
IN_PROC_BROWSER_TEST_F(TermsOfServiceScreenTest,Accepted)232 IN_PROC_BROWSER_TEST_F(TermsOfServiceScreenTest, Accepted) {
233   SetUpTermsOfServiceUrlPolicy();
234   StartPublicSession();
235 
236   WaitFosScreenShown();
237   SetUpExitCallback();
238 
239   test::OobeJS().TapOnPath({"terms-of-service", "acceptButton"});
240 
241   WaitForScreenExit();
242   EXPECT_EQ(result_.value(), TermsOfServiceScreen::Result::ACCEPTED);
243   histogram_tester_.ExpectTotalCount(
244       "OOBE.StepCompletionTimeByExitReason.Terms-of-service.Accepted", 1);
245   histogram_tester_.ExpectTotalCount(
246       "OOBE.StepCompletionTimeByExitReason.Terms-of-service.Declined", 0);
247   histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Tos", 1);
248 
249   chromeos::test::WaitForPrimaryUserSessionStart();
250 }
251 
IN_PROC_BROWSER_TEST_F(TermsOfServiceScreenTest,Declined)252 IN_PROC_BROWSER_TEST_F(TermsOfServiceScreenTest, Declined) {
253   SetUpTermsOfServiceUrlPolicy();
254   StartPublicSession();
255 
256   WaitFosScreenShown();
257   SetUpExitCallback();
258 
259   test::OobeJS().TapOnPath({"terms-of-service", "backButton"});
260   WaitForScreenExit();
261   EXPECT_EQ(result_.value(), TermsOfServiceScreen::Result::DECLINED);
262   histogram_tester_.ExpectTotalCount(
263       "OOBE.StepCompletionTimeByExitReason.Terms-of-service.Accepted", 0);
264   histogram_tester_.ExpectTotalCount(
265       "OOBE.StepCompletionTimeByExitReason.Terms-of-service.Declined", 1);
266   histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Tos", 1);
267 
268   EXPECT_TRUE(session_manager_client()->session_stopped());
269   EXPECT_TRUE(ash::LoginScreenTestApi::IsPublicSessionExpanded());
270 }
271 
272 }  // namespace chromeos
273