1 // Copyright 2018 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/ui/webui/about_ui.h"
6
7 #include <memory>
8 #include <string>
9
10 #include "base/base64.h"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/files/file_path.h"
14 #include "base/files/file_util.h"
15 #include "base/files/scoped_temp_dir.h"
16 #include "base/macros.h"
17 #include "base/memory/ref_counted_memory.h"
18 #include "base/strings/strcat.h"
19 #include "base/strings/string_piece.h"
20 #include "base/strings/string_util.h"
21 #include "base/task/post_task.h"
22 #include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
23 #include "chrome/browser/chromeos/login/ui/fake_login_display_host.h"
24 #include "chrome/browser/chromeos/login/wizard_controller.h"
25 #include "chrome/browser/ui/webui/chromeos/login/demo_preferences_screen_handler.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/common/webui_url_constants.h"
28 #include "chrome/test/base/scoped_browser_locale.h"
29 #include "chromeos/dbus/dbus_thread_manager.h"
30 #include "chromeos/system/fake_statistics_provider.h"
31 #include "chromeos/system/statistics_provider.h"
32 #include "content/public/browser/browser_task_traits.h"
33 #include "content/public/test/browser_task_environment.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36
37 namespace {
38
39 class TestDataReceiver {
40 public:
41 TestDataReceiver() = default;
42 virtual ~TestDataReceiver() = default;
43
data_received() const44 bool data_received() const { return data_received_; }
45
data() const46 std::string data() const { return data_; }
47
Base64DecodedData() const48 std::string Base64DecodedData() const {
49 std::string decoded;
50 base::Base64Decode(data_, &decoded);
51 return decoded;
52 }
53
OnDataReceived(scoped_refptr<base::RefCountedMemory> bytes)54 void OnDataReceived(scoped_refptr<base::RefCountedMemory> bytes) {
55 data_received_ = true;
56 data_ = base::StringPiece(reinterpret_cast<const char*>(bytes->front()),
57 bytes->size())
58 .as_string();
59 }
60
61 private:
62 bool data_received_ = false;
63 std::string data_;
64
65 DISALLOW_COPY_AND_ASSIGN(TestDataReceiver);
66 };
67
68 } // namespace
69
70 // Base class for ChromeOS offline terms tests.
71 class ChromeOSTermsTest : public testing::Test {
72 protected:
ChromeOSTermsTest()73 ChromeOSTermsTest() {}
74 ~ChromeOSTermsTest() override = default;
75
SetUp()76 void SetUp() override {
77 // Create root tmp directory for fake ARC ToS data.
78 base::FilePath root_path;
79 base::CreateNewTempDirectory(FILE_PATH_LITERAL(""), &root_path);
80 ASSERT_TRUE(preinstalled_offline_resources_dir_.Set(root_path));
81 arc_tos_dir_ =
82 preinstalled_offline_resources_dir_.GetPath().Append("arc_tos");
83 ASSERT_TRUE(base::CreateDirectory(arc_tos_dir_));
84
85 tested_html_source_ = std::make_unique<AboutUIHTMLSource>(
86 chrome::kChromeUITermsHost, nullptr);
87 }
88
89 // Creates directory for the given |locale| that contains terms.html. Writes
90 // the |locale| string to the created file.
CreateTermsForLocale(const std::string & locale)91 bool CreateTermsForLocale(const std::string& locale) {
92 base::FilePath dir = arc_tos_dir_.Append(base::ToLowerASCII(locale));
93 if (!base::CreateDirectory(dir))
94 return false;
95
96 if (base::WriteFile(dir.AppendASCII("terms.html"), locale.c_str(),
97 locale.length()) != static_cast<int>(locale.length())) {
98 return false;
99 }
100 return true;
101 }
102
103 // Creates directory for the given |locale| that contains privacy_policy.pdf.
104 // Writes the |locale| string to the created file.
CreatePrivacyPolicyForLocale(const std::string & locale)105 bool CreatePrivacyPolicyForLocale(const std::string& locale) {
106 base::FilePath dir = arc_tos_dir_.Append(base::ToLowerASCII(locale));
107 if (!base::CreateDirectory(dir))
108 return false;
109
110 if (base::WriteFile(dir.AppendASCII("privacy_policy.pdf"), locale.c_str(),
111 locale.length()) != static_cast<int>(locale.length())) {
112 return false;
113 }
114 return true;
115 }
116
117 // Sets device region in VPD.
SetRegion(const std::string & region)118 void SetRegion(const std::string& region) {
119 statistics_provider_.SetMachineStatistic(chromeos::system::kRegionKey,
120 region);
121 }
122
123 // Starts data request with the |request_url|.
StartRequest(const std::string & request_url,TestDataReceiver * data_receiver)124 void StartRequest(const std::string& request_url,
125 TestDataReceiver* data_receiver) {
126 content::WebContents::Getter wc_getter;
127 tested_html_source_->StartDataRequest(
128 GURL(base::StrCat(
129 {"chrome://", chrome::kChromeUITermsHost, "/", request_url})),
130 std::move(wc_getter),
131 base::BindRepeating(&TestDataReceiver::OnDataReceived,
132 base::Unretained(data_receiver)));
133 task_environment_.RunUntilIdle();
134 }
135
PreinstalledOfflineResourcesPath()136 const base::FilePath& PreinstalledOfflineResourcesPath() {
137 return preinstalled_offline_resources_dir_.GetPath();
138 }
139
140 private:
141 base::ScopedTempDir preinstalled_offline_resources_dir_;
142 base::FilePath arc_tos_dir_;
143
144 content::BrowserTaskEnvironment task_environment_;
145
146 chromeos::system::ScopedFakeStatisticsProvider statistics_provider_;
147
148 std::unique_ptr<AboutUIHTMLSource> tested_html_source_;
149
150 DISALLOW_COPY_AND_ASSIGN(ChromeOSTermsTest);
151 };
152
TEST_F(ChromeOSTermsTest,NoData)153 TEST_F(ChromeOSTermsTest, NoData) {
154 SetRegion("ca");
155 ScopedBrowserLocale browser_locale("en-CA");
156
157 TestDataReceiver terms_data_receiver;
158 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
159
160 EXPECT_TRUE(terms_data_receiver.data_received());
161 EXPECT_EQ("", terms_data_receiver.data());
162
163 TestDataReceiver privacy_policy_data_receiver;
164 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_policy_data_receiver);
165
166 EXPECT_TRUE(privacy_policy_data_receiver.data_received());
167 EXPECT_EQ("", privacy_policy_data_receiver.data());
168 }
169
170 // Demo mode ARC++ ToS and privacy policy test.
171 class DemoModeChromeOSTermsTest : public ChromeOSTermsTest {
172 protected:
173 DemoModeChromeOSTermsTest() = default;
174 ~DemoModeChromeOSTermsTest() override = default;
175
SetUp()176 void SetUp() override {
177 ChromeOSTermsTest::SetUp();
178 AddDemoModeLocale();
179
180 // Simulate Demo Mode setup.
181 chromeos::DBusThreadManager::Initialize();
182 fake_login_display_host_ =
183 std::make_unique<chromeos::FakeLoginDisplayHost>();
184 fake_login_display_host_->StartWizard(
185 chromeos::DemoPreferencesScreenView::kScreenId);
186 fake_login_display_host_->GetWizardController()
187 ->SimulateDemoModeSetupForTesting();
188 fake_login_display_host_->GetWizardController()
189 ->demo_setup_controller()
190 ->SetPreinstalledOfflineResourcesPathForTesting(
191 PreinstalledOfflineResourcesPath());
192 fake_login_display_host_->GetWizardController()
193 ->demo_setup_controller()
194 ->TryMountPreinstalledDemoResources(base::DoNothing());
195 }
196
TearDown()197 void TearDown() override { chromeos::DBusThreadManager::Shutdown(); }
198
199 // Adds locales supported by demo mode.
AddDemoModeLocale()200 void AddDemoModeLocale() {
201 ASSERT_TRUE(CreateTermsForLocale("apac"));
202 ASSERT_TRUE(CreateTermsForLocale("da-DK"));
203 ASSERT_TRUE(CreateTermsForLocale("de-de"));
204 ASSERT_TRUE(CreateTermsForLocale("emea"));
205 ASSERT_TRUE(CreateTermsForLocale("en-CA"));
206 ASSERT_TRUE(CreateTermsForLocale("en-GB"));
207 ASSERT_TRUE(CreateTermsForLocale("en-IE"));
208 ASSERT_TRUE(CreateTermsForLocale("en-US"));
209 ASSERT_TRUE(CreateTermsForLocale("eu"));
210 ASSERT_TRUE(CreateTermsForLocale("fi-FI"));
211 ASSERT_TRUE(CreateTermsForLocale("fr-BE"));
212 ASSERT_TRUE(CreateTermsForLocale("fr-CA"));
213 ASSERT_TRUE(CreateTermsForLocale("fr-FR"));
214 ASSERT_TRUE(CreateTermsForLocale("ko-KR"));
215 ASSERT_TRUE(CreateTermsForLocale("nb-NO"));
216 ASSERT_TRUE(CreateTermsForLocale("nl-BE"));
217 ASSERT_TRUE(CreateTermsForLocale("nl-NL"));
218 ASSERT_TRUE(CreateTermsForLocale("sv-SE"));
219
220 ASSERT_TRUE(CreatePrivacyPolicyForLocale("da-DK"));
221 ASSERT_TRUE(CreatePrivacyPolicyForLocale("de-de"));
222 ASSERT_TRUE(CreatePrivacyPolicyForLocale("en-US"));
223 ASSERT_TRUE(CreatePrivacyPolicyForLocale("eu"));
224 ASSERT_TRUE(CreatePrivacyPolicyForLocale("fi-FI"));
225 ASSERT_TRUE(CreatePrivacyPolicyForLocale("fr-BE"));
226 ASSERT_TRUE(CreatePrivacyPolicyForLocale("fr-CA"));
227 ASSERT_TRUE(CreatePrivacyPolicyForLocale("fr-FR"));
228 ASSERT_TRUE(CreatePrivacyPolicyForLocale("ko-KR"));
229 ASSERT_TRUE(CreatePrivacyPolicyForLocale("nb-NO"));
230 ASSERT_TRUE(CreatePrivacyPolicyForLocale("nl-BE"));
231 ASSERT_TRUE(CreatePrivacyPolicyForLocale("nl-NL"));
232 ASSERT_TRUE(CreatePrivacyPolicyForLocale("sv-SE"));
233 }
234
235 private:
236 std::unique_ptr<chromeos::FakeLoginDisplayHost> fake_login_display_host_;
237
238 DISALLOW_COPY_AND_ASSIGN(DemoModeChromeOSTermsTest);
239 };
240
TEST_F(DemoModeChromeOSTermsTest,TermsSimpleRegion)241 TEST_F(DemoModeChromeOSTermsTest, TermsSimpleRegion) {
242 SetRegion("ca");
243 for (const char* locale : {"en-CA", "fr-CA"}) {
244 ScopedBrowserLocale browser_locale(locale);
245
246 TestDataReceiver data_receiver;
247 StartRequest(chrome::kArcTermsURLPath, &data_receiver);
248
249 EXPECT_TRUE(data_receiver.data_received());
250 EXPECT_EQ(locale, data_receiver.data());
251 }
252 }
253
TEST_F(DemoModeChromeOSTermsTest,ComplexRegion)254 TEST_F(DemoModeChromeOSTermsTest, ComplexRegion) {
255 const std::string kLocale = "en-CA";
256 ScopedBrowserLocale browser_locale(kLocale);
257 for (const char* region :
258 {"ca.hybridansi", "ca.ansi", "ca.multix", "ca.fr"}) {
259 SetRegion(region);
260
261 TestDataReceiver terms_data_receiver;
262 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
263
264 EXPECT_TRUE(terms_data_receiver.data_received());
265 EXPECT_EQ(kLocale, terms_data_receiver.data());
266
267 TestDataReceiver privacy_data_receiver;
268 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
269
270 // Privacy policy for en-CA defaults to en-US.
271 EXPECT_TRUE(privacy_data_receiver.data_received());
272 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
273 }
274 }
275
TEST_F(DemoModeChromeOSTermsTest,NotCaseSensitive)276 TEST_F(DemoModeChromeOSTermsTest, NotCaseSensitive) {
277 SetRegion("CA");
278 for (const char* locale : {"EN-CA", "en-CA", "EN-ca"}) {
279 ScopedBrowserLocale browser_locale(locale);
280
281 TestDataReceiver terms_data_receiver;
282 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
283
284 EXPECT_TRUE(terms_data_receiver.data_received());
285 EXPECT_EQ("en-CA", terms_data_receiver.data());
286
287 TestDataReceiver privacy_data_receiver;
288 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
289
290 // Privacy policy for en-CA defaults to en-US.
291 EXPECT_TRUE(privacy_data_receiver.data_received());
292 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
293 }
294 }
295
TEST_F(DemoModeChromeOSTermsTest,DefaultsForEuRegion)296 TEST_F(DemoModeChromeOSTermsTest, DefaultsForEuRegion) {
297 const std::string kLocale = "pl-PL";
298 ScopedBrowserLocale browser_locale(kLocale);
299 SetRegion("pl");
300
301 TestDataReceiver terms_data_receiver;
302 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
303
304 EXPECT_TRUE(terms_data_receiver.data_received());
305 EXPECT_EQ("eu", terms_data_receiver.data());
306
307 TestDataReceiver privacy_data_receiver;
308 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
309
310 EXPECT_TRUE(privacy_data_receiver.data_received());
311 EXPECT_EQ("eu", privacy_data_receiver.Base64DecodedData());
312 }
313
TEST_F(DemoModeChromeOSTermsTest,DefaultsForEmeaRegion)314 TEST_F(DemoModeChromeOSTermsTest, DefaultsForEmeaRegion) {
315 const std::string kLocale = "fr-CH";
316 ScopedBrowserLocale browser_locale(kLocale);
317 SetRegion("ch");
318
319 TestDataReceiver terms_data_receiver;
320 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
321
322 EXPECT_TRUE(terms_data_receiver.data_received());
323 EXPECT_EQ("emea", terms_data_receiver.data());
324
325 TestDataReceiver privacy_data_receiver;
326 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
327
328 // Privacy policy for EMEA defaults to en-US.
329 EXPECT_TRUE(privacy_data_receiver.data_received());
330 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
331 }
332
TEST_F(DemoModeChromeOSTermsTest,DefaultsForApacRegion)333 TEST_F(DemoModeChromeOSTermsTest, DefaultsForApacRegion) {
334 const std::string kLocale = "en-PH";
335 ScopedBrowserLocale browser_locale(kLocale);
336 SetRegion("ph");
337
338 TestDataReceiver terms_data_receiver;
339 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
340
341 EXPECT_TRUE(terms_data_receiver.data_received());
342 EXPECT_EQ("apac", terms_data_receiver.data());
343
344 TestDataReceiver privacy_data_receiver;
345 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
346
347 // Privacy policy for APAC defaults to en-US.
348 EXPECT_TRUE(privacy_data_receiver.data_received());
349 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
350 }
351
TEST_F(DemoModeChromeOSTermsTest,DefaultsForAmericasRegion)352 TEST_F(DemoModeChromeOSTermsTest, DefaultsForAmericasRegion) {
353 const std::string kLocale = "en-MX";
354 ScopedBrowserLocale browser_locale(kLocale);
355 SetRegion("mx");
356
357 // Both ToS and privacy policy default to en-US for AMERICAS.
358 TestDataReceiver terms_data_receiver;
359 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
360
361 EXPECT_TRUE(terms_data_receiver.data_received());
362 EXPECT_EQ("en-US", terms_data_receiver.data());
363
364 TestDataReceiver privacy_data_receiver;
365 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
366
367 EXPECT_TRUE(privacy_data_receiver.data_received());
368 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
369 }
370
TEST_F(DemoModeChromeOSTermsTest,DefaultsToEnUs)371 TEST_F(DemoModeChromeOSTermsTest, DefaultsToEnUs) {
372 const std::string kLocale = "en-SA";
373 ScopedBrowserLocale browser_locale(kLocale);
374 SetRegion("sa");
375
376 TestDataReceiver terms_data_receiver;
377 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
378
379 EXPECT_TRUE(terms_data_receiver.data_received());
380 EXPECT_EQ("en-US", terms_data_receiver.data());
381
382 TestDataReceiver privacy_data_receiver;
383 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
384
385 EXPECT_TRUE(privacy_data_receiver.data_received());
386 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
387 }
388
TEST_F(DemoModeChromeOSTermsTest,NoLangCountryCombination)389 TEST_F(DemoModeChromeOSTermsTest, NoLangCountryCombination) {
390 SetRegion("be");
391 {
392 const std::string kLocale = "nl-BE";
393 ScopedBrowserLocale browser_locale(kLocale);
394
395 TestDataReceiver terms_data_receiver;
396 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
397
398 EXPECT_TRUE(terms_data_receiver.data_received());
399 EXPECT_EQ(kLocale, terms_data_receiver.data());
400
401 TestDataReceiver privacy_data_receiver;
402 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
403
404 EXPECT_TRUE(privacy_data_receiver.data_received());
405 EXPECT_EQ(kLocale, privacy_data_receiver.Base64DecodedData());
406 }
407 {
408 const std::string kLocale = "de-BE";
409 ScopedBrowserLocale browser_locale(kLocale);
410
411 TestDataReceiver terms_data_receiver;
412 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
413
414 // No language - country combination - defaults to region.
415 EXPECT_TRUE(terms_data_receiver.data_received());
416 EXPECT_EQ("eu", terms_data_receiver.data());
417
418 TestDataReceiver privacy_data_receiver;
419 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
420
421 EXPECT_TRUE(privacy_data_receiver.data_received());
422 EXPECT_EQ("eu", privacy_data_receiver.Base64DecodedData());
423 }
424 }
425
TEST_F(DemoModeChromeOSTermsTest,InvalidRegion)426 TEST_F(DemoModeChromeOSTermsTest, InvalidRegion) {
427 const std::string kLocale = "da-DK";
428 ScopedBrowserLocale browser_locale(kLocale);
429 for (const char* region : {"", " ", ".", "..", "-", "xyz"}) {
430 SetRegion(region);
431 TestDataReceiver terms_data_receiver;
432 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
433
434 EXPECT_TRUE(terms_data_receiver.data_received());
435 EXPECT_EQ("en-US", terms_data_receiver.data());
436
437 TestDataReceiver privacy_data_receiver;
438 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
439
440 EXPECT_TRUE(privacy_data_receiver.data_received());
441 EXPECT_EQ("en-US", privacy_data_receiver.Base64DecodedData());
442 }
443 }
444
TEST_F(DemoModeChromeOSTermsTest,InvalidLocale)445 TEST_F(DemoModeChromeOSTermsTest, InvalidLocale) {
446 SetRegion("se");
447 for (const char* locale : {"", " ", ".", "-", "-sv"}) {
448 ScopedBrowserLocale browser_locale(locale);
449
450 TestDataReceiver terms_data_receiver;
451 StartRequest(chrome::kArcTermsURLPath, &terms_data_receiver);
452
453 EXPECT_TRUE(terms_data_receiver.data_received());
454 EXPECT_EQ("eu", terms_data_receiver.data());
455
456 TestDataReceiver privacy_data_receiver;
457 StartRequest(chrome::kArcPrivacyPolicyURLPath, &privacy_data_receiver);
458
459 EXPECT_TRUE(privacy_data_receiver.data_received());
460 EXPECT_EQ("eu", privacy_data_receiver.Base64DecodedData());
461 }
462 }
463