[M85 Dev][EFL] Fix errors to generate ninja files
[platform/framework/web/chromium-efl.git] / chrome / browser / about_flags_browsertest.cc
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 "base/command_line.h"
6 #include "base/strings/stringprintf.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/test/bind_test_util.h"
9 #include "base/test/scoped_feature_list.h"
10 #include "build/build_config.h"
11 #include "chrome/browser/about_flags.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/browser/unexpire_flags.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/interactive_test_utils.h"
17 #include "chrome/test/base/ui_test_utils.h"
18 #include "components/flags_ui/feature_entry_macros.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/test/browser_test.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "ui/base/window_open_disposition.h"
23
24 namespace {
25
26 const char kSwitchName[] = "flag-system-test-switch";
27 const char kFlagName[] = "flag-system-test-flag-1";
28
29 const char kExpiredFlagName[] = "flag-system-test-flag-2";
30 const char kExpiredFlagSwitchName[] = "flag-system-test-expired-switch";
31
32 const char kFlagWithOptionSelectorName[] = "flag-system-test-flag-3";
33 const char kFlagWithOptionSelectorSwitchName[] = "flag-system-test-switch";
34
35 // Command line switch containing an invalid origin.
36 const char kUnsanitizedCommandLine[] =
37     "http://example-cmdline.test,invalid-cmdline";
38
39 // Command line switch without the invalid origin.
40 const char kSanitizedCommandLine[] = "http://example-cmdline.test";
41
42 // User input containing invalid origins.
43 const char kUnsanitizedInput[] =
44     "http://example.test/path    http://example2.test/?query\n"
45     "invalid-value, filesystem:http://example.test.file, "
46     "ws://example3.test http://&^.com";
47
48 // User input with invalid origins removed and formatted.
49 const char kSanitizedInput[] =
50     "http://example.test,http://example2.test,ws://example3.test";
51
52 // Command Line + user input with invalid origins removed and formatted.
53 const char kSanitizedInputAndCommandLine[] =
54     "http://example-cmdline.test,http://example.test,http://"
55     "example2.test,ws://example3.test";
56
57 void SimulateTextType(content::WebContents* contents,
58                       const char* experiment_id,
59                       const char* text) {
60   EXPECT_TRUE(content::ExecuteScript(
61       contents, base::StringPrintf(
62                     "var parent = document.getElementById('%s');"
63                     "var textarea = parent.getElementsByTagName('textarea')[0];"
64                     "textarea.focus();"
65                     "textarea.value = `%s`;"
66                     "textarea.onchange();",
67                     experiment_id, text)));
68 }
69
70 void ToggleEnableDropdown(content::WebContents* contents,
71                           const char* experiment_id,
72                           bool enable) {
73   EXPECT_TRUE(content::ExecuteScript(
74       contents,
75       base::StringPrintf(
76           "var k = document.getElementById('%s');"
77           "var s = k.getElementsByClassName('experiment-enable-disable')[0];"
78           "s.focus();"
79           "s.selectedIndex = %d;"
80           "s.onchange();",
81           experiment_id, enable ? 1 : 0)));
82 }
83
84 std::string GetOriginListText(content::WebContents* contents,
85                               const char* experiment_id) {
86   std::string text;
87   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
88       contents,
89       base::StringPrintf(
90           "var k = document.getElementById('%s');"
91           "var s = k.getElementsByClassName('experiment-origin-list-value')[0];"
92           "window.domAutomationController.send(s.value );",
93           experiment_id),
94       &text));
95   return text;
96 }
97
98 bool IsDropdownEnabled(content::WebContents* contents,
99                        const char* experiment_id) {
100   bool result = false;
101   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
102       contents,
103       base::StringPrintf(
104           "var k = document.getElementById('%s');"
105           "var s = k.getElementsByClassName('experiment-enable-disable')[0];"
106           "window.domAutomationController.send(s.value == 'enabled');",
107           experiment_id),
108       &result));
109   return result;
110 }
111
112 bool IsFlagPresent(content::WebContents* contents, const char* experiment_id) {
113   bool result = false;
114   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
115       contents,
116       base::StringPrintf("var k = document.getElementById('%s');"
117                          "window.domAutomationController.send(k != null);",
118                          experiment_id),
119       &result));
120   return result;
121 }
122
123 void WaitForExperimentalFeatures(content::WebContents* contents) {
124   bool unused;
125   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
126       contents,
127       "experimentalFeaturesReady.then(() => {"
128       "  window.domAutomationController.send(true);"
129       "});",
130       &unused));
131 }
132
133 // In these tests, valid origins in the existing command line flag will be
134 // appended to the list entered by the user in chrome://flags.
135 // The tests are run twice for each bool value: Once with an existing command
136 // line (provided in SetUpCommandLine) and once without.
137 class AboutFlagsBrowserTest : public InProcessBrowserTest,
138                               public testing::WithParamInterface<bool> {
139  public:
140   AboutFlagsBrowserTest() {
141     about_flags::testing::SetFeatureEntries(
142         {{kFlagName, "name-1", "description-1", -1,
143           ORIGIN_LIST_VALUE_TYPE(kSwitchName, "")},
144          {kExpiredFlagName, "name-2", "description-2", -1,
145           SINGLE_VALUE_TYPE(kExpiredFlagSwitchName)},
146          {kFlagWithOptionSelectorName, "name-3", "description-3", -1,
147           SINGLE_VALUE_TYPE(kFlagWithOptionSelectorSwitchName)}});
148     flags::testing::SetFlagExpiredPredicate(
149         base::BindLambdaForTesting([&](const std::string& name) -> bool {
150           return expiration_enabled_ && name == kExpiredFlagName;
151         }));
152   }
153
154   void SetUpCommandLine(base::CommandLine* command_line) override {
155     command_line->AppendSwitchASCII(kSwitchName, GetInitialCommandLine());
156   }
157
158  protected:
159   void set_expiration_enabled(bool enabled) { expiration_enabled_ = enabled; }
160
161   bool has_initial_command_line() const { return GetParam(); }
162
163   std::string GetInitialCommandLine() const {
164     return has_initial_command_line() ? kUnsanitizedCommandLine : std::string();
165   }
166
167   std::string GetSanitizedCommandLine() const {
168     return has_initial_command_line() ? kSanitizedCommandLine : std::string();
169   }
170
171   std::string GetSanitizedInputAndCommandLine() const {
172     return has_initial_command_line() ? kSanitizedInputAndCommandLine
173                                       : kSanitizedInput;
174   }
175
176   void NavigateToFlagsPage() {
177     ui_test_utils::NavigateToURL(browser(), GURL("chrome://flags"));
178     WaitForExperimentalFeatures(
179         browser()->tab_strip_model()->GetActiveWebContents());
180   }
181
182   bool expiration_enabled_ = true;
183
184   base::test::ScopedFeatureList feature_list_;
185 };
186
187 INSTANTIATE_TEST_SUITE_P(All,
188                          AboutFlagsBrowserTest,
189                          ::testing::Values(true, false));
190
191 // Goes to chrome://flags page, types text into an ORIGIN_LIST_VALUE field but
192 // does not enable the feature.
193 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, PRE_OriginFlagDisabled) {
194   NavigateToFlagsPage();
195
196   const base::CommandLine::SwitchMap kInitialSwitches =
197       base::CommandLine::ForCurrentProcess()->GetSwitches();
198
199   content::WebContents* contents =
200       browser()->tab_strip_model()->GetActiveWebContents();
201
202   // The page should be populated with the sanitized command line value.
203   EXPECT_EQ(GetSanitizedCommandLine(), GetOriginListText(contents, kFlagName));
204
205   // Type a value in the experiment's textarea. Since the flag state is
206   // "Disabled" by default, command line shouldn't change.
207   SimulateTextType(contents, kFlagName, kUnsanitizedInput);
208   EXPECT_EQ(kInitialSwitches,
209             base::CommandLine::ForCurrentProcess()->GetSwitches());
210
211   // Input should be restored after a page reload.
212   NavigateToFlagsPage();
213   EXPECT_EQ(GetSanitizedInputAndCommandLine(),
214             GetOriginListText(contents, kFlagName));
215 }
216
217 // Flaky. http://crbug.com/1010678
218 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, DISABLED_OriginFlagDisabled) {
219   // Even though the feature is disabled, the switch is set directly via command
220   // line.
221   EXPECT_EQ(
222       GetInitialCommandLine(),
223       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchName));
224
225   NavigateToFlagsPage();
226   content::WebContents* contents =
227       browser()->tab_strip_model()->GetActiveWebContents();
228   EXPECT_FALSE(IsDropdownEnabled(contents, kFlagName));
229   EXPECT_EQ(GetSanitizedInputAndCommandLine(),
230             GetOriginListText(contents, kFlagName));
231 }
232
233 // Goes to chrome://flags page, types text into an ORIGIN_LIST_VALUE field and
234 // enables the feature.
235 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, PRE_OriginFlagEnabled) {
236   NavigateToFlagsPage();
237
238   const base::CommandLine::SwitchMap kInitialSwitches =
239       base::CommandLine::ForCurrentProcess()->GetSwitches();
240
241   content::WebContents* contents =
242       browser()->tab_strip_model()->GetActiveWebContents();
243
244   // The page should be populated with the sanitized command line value.
245   EXPECT_EQ(GetSanitizedCommandLine(), GetOriginListText(contents, kFlagName));
246
247   // Type a value in the experiment's textarea. Since the flag state is
248   // "Disabled" by default, command line shouldn't change.
249   SimulateTextType(contents, kFlagName, kUnsanitizedInput);
250   EXPECT_EQ(kInitialSwitches,
251             base::CommandLine::ForCurrentProcess()->GetSwitches());
252
253   // Enable the experiment. The behavior is different between ChromeOS and
254   // non-ChromeOS.
255   ToggleEnableDropdown(contents, kFlagName, true);
256
257 #if !defined(OS_CHROMEOS)
258   // On non-ChromeOS, the command line is not modified until restart.
259   EXPECT_EQ(kInitialSwitches,
260             base::CommandLine::ForCurrentProcess()->GetSwitches());
261 #else
262   // On ChromeOS, the command line is immediately modified.
263   EXPECT_NE(kInitialSwitches,
264             base::CommandLine::ForCurrentProcess()->GetSwitches());
265   EXPECT_EQ(
266       GetSanitizedInputAndCommandLine(),
267       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchName));
268 #endif
269
270   // Input should be restored after a page reload.
271   NavigateToFlagsPage();
272   EXPECT_EQ(GetSanitizedInputAndCommandLine(),
273             GetOriginListText(contents, kFlagName));
274 }
275
276 // Flaky. http://crbug.com/1010678
277 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, DISABLED_OriginFlagEnabled) {
278 #if !defined(OS_CHROMEOS)
279   // On non-ChromeOS, the command line is modified after restart.
280   EXPECT_EQ(
281       GetSanitizedInputAndCommandLine(),
282       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchName));
283 #else
284   // On ChromeOS, the command line isn't modified after restart.
285   EXPECT_EQ(
286       GetInitialCommandLine(),
287       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchName));
288 #endif
289
290   NavigateToFlagsPage();
291   content::WebContents* contents =
292       browser()->tab_strip_model()->GetActiveWebContents();
293   EXPECT_TRUE(IsDropdownEnabled(contents, kFlagName));
294   EXPECT_EQ(GetSanitizedInputAndCommandLine(),
295             GetOriginListText(contents, kFlagName));
296
297 #if defined(OS_CHROMEOS)
298   // ChromeOS doesn't read chrome://flags values on startup so we explicitly
299   // need to disable and re-enable the flag here.
300   ToggleEnableDropdown(contents, kFlagName, true);
301 #endif
302
303   EXPECT_EQ(
304       GetSanitizedInputAndCommandLine(),
305       base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kSwitchName));
306 }
307
308 // Crashes on Win.  http://crbug.com/1025213
309 #if defined(OS_WIN)
310 #define MAYBE_ExpiryHidesFlag DISABLED_ExpiryHidesFlag
311 #else
312 #define MAYBE_ExpiryHidesFlag ExpiryHidesFlag
313 #endif
314 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, MAYBE_ExpiryHidesFlag) {
315   NavigateToFlagsPage();
316   content::WebContents* contents =
317       browser()->tab_strip_model()->GetActiveWebContents();
318   EXPECT_TRUE(IsFlagPresent(contents, kFlagName));
319   EXPECT_FALSE(IsFlagPresent(contents, kExpiredFlagName));
320
321   set_expiration_enabled(false);
322
323   NavigateToFlagsPage();
324   contents = browser()->tab_strip_model()->GetActiveWebContents();
325   EXPECT_TRUE(IsFlagPresent(contents, kFlagName));
326   EXPECT_TRUE(IsFlagPresent(contents, kExpiredFlagName));
327 }
328
329 #if !defined(OS_CHROMEOS)
330 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, PRE_ExpiredFlagDoesntApply) {
331   set_expiration_enabled(false);
332   NavigateToFlagsPage();
333   content::WebContents* contents =
334       browser()->tab_strip_model()->GetActiveWebContents();
335   EXPECT_TRUE(IsFlagPresent(contents, kExpiredFlagName));
336   EXPECT_FALSE(IsDropdownEnabled(contents, kExpiredFlagName));
337
338   ToggleEnableDropdown(contents, kExpiredFlagName, true);
339 }
340
341 // Flaky everywhere: https://crbug.com/1024028
342 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, DISABLED_ExpiredFlagDoesntApply) {
343   set_expiration_enabled(true);
344   NavigateToFlagsPage();
345   content::WebContents* contents =
346       browser()->tab_strip_model()->GetActiveWebContents();
347   EXPECT_FALSE(IsFlagPresent(contents, kExpiredFlagName));
348
349   EXPECT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
350       kExpiredFlagSwitchName));
351 }
352 #endif
353
354 IN_PROC_BROWSER_TEST_P(AboutFlagsBrowserTest, FormRestore) {
355   NavigateToFlagsPage();
356   content::WebContents* contents =
357       browser()->tab_strip_model()->GetActiveWebContents();
358
359   // Remove the internal_name property from a flag's selector, then synthesize a
360   // change event for it. This simulates what happens during form restoration in
361   // Blink, when navigating back and then forward to the flags page. This test
362   // ensures that that does not crash the browser.
363   // See https://crbug.com/1038638 for more details.
364   EXPECT_TRUE(content::ExecJs(
365       contents,
366       base::StringPrintf(
367           "var k = document.getElementById('%s');"
368           "var s = k.getElementsByClassName('experiment-enable-disable')[0];"
369           "delete s.internal_name;"
370           "const e = document.createEvent('HTMLEvents');"
371           "e.initEvent('change', true, true);"
372           "s.dispatchEvent(e);",
373           kFlagWithOptionSelectorName)));
374 }
375
376 }  // namespace