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 "content/web_test/browser/web_test_browser_main_runner.h"
6
7 #include <iostream>
8 #include <memory>
9
10 #include "base/bind.h"
11 #include "base/check_op.h"
12 #include "base/command_line.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/location.h"
17 #include "base/run_loop.h"
18 #include "base/single_thread_task_runner.h"
19 #include "base/strings/sys_string_conversions.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "base/threading/thread_task_runner_handle.h"
23 #include "build/build_config.h"
24 #include "cc/base/switches.h"
25 #include "components/network_session_configurator/common/network_switches.h"
26 #include "components/viz/common/switches.h"
27 #include "content/browser/renderer_host/render_widget_host_impl.h"
28 #include "content/public/browser/browser_main_runner.h"
29 #include "content/public/common/content_switches.h"
30 #include "content/public/common/url_constants.h"
31 #include "content/public/test/ppapi_test_utils.h"
32 #include "content/shell/browser/shell.h"
33 #include "content/shell/common/shell_switches.h"
34 #include "content/test/gpu_browsertest_helpers.h"
35 #include "content/web_test/browser/test_info_extractor.h"
36 #include "content/web_test/browser/web_test_browser_main_platform_support.h"
37 #include "content/web_test/browser/web_test_control_host.h"
38 #include "content/web_test/common/web_test_switches.h"
39 #include "gpu/config/gpu_switches.h"
40 #include "gpu/ipc/client/gpu_channel_host.h"
41 #include "media/base/media_switches.h"
42 #include "net/base/filename_util.h"
43 #include "ppapi/buildflags/buildflags.h"
44 #include "services/network/public/cpp/network_switches.h"
45 #include "ui/base/ui_base_switches.h"
46 #include "ui/display/display_switches.h"
47 #include "ui/gl/gl_implementation.h"
48 #include "ui/gl/gl_switches.h"
49
50 namespace content {
51
52 namespace {
53
RunOneTest(const content::TestInfo & test_info,content::WebTestControlHost * web_test_control_host,content::BrowserMainRunner * main_runner)54 bool RunOneTest(const content::TestInfo& test_info,
55 content::WebTestControlHost* web_test_control_host,
56 content::BrowserMainRunner* main_runner) {
57 TRACE_EVENT0("shell", "WebTestBrowserMainRunner::RunOneTest");
58 DCHECK(web_test_control_host);
59
60 if (!web_test_control_host->PrepareForWebTest(test_info))
61 return false;
62
63 main_runner->Run();
64
65 return web_test_control_host->ResetBrowserAfterWebTest();
66 }
67
RunTests(content::BrowserMainRunner * main_runner)68 void RunTests(content::BrowserMainRunner* main_runner) {
69 TRACE_EVENT0("shell", "WebTestBrowserMainRunner::RunTests");
70 content::WebTestControlHost test_controller;
71 {
72 // We're outside of the message loop here, and this is a test.
73 base::ScopedAllowBlockingForTesting allow_blocking;
74 base::FilePath temp_path;
75 base::GetTempDir(&temp_path);
76 test_controller.SetTempPath(temp_path);
77 }
78
79 {
80 // Kick off the launch of the GPU process early, to minimize blocking
81 // startup of the first renderer process in PrepareForWebTest. (This avoids
82 // GPU process startup time from being counted in the first test's timeout,
83 // hopefully making it less likely to time out flakily.)
84 // https://crbug.com/953991
85 TRACE_EVENT0("shell",
86 "WebTestBrowserMainRunner::RunTests::EstablishGpuChannelSync");
87 content::GpuBrowsertestEstablishGpuChannelSyncRunLoop();
88 }
89
90 std::cout << "#READY\n";
91 std::cout.flush();
92
93 content::TestInfoExtractor test_extractor(
94 *base::CommandLine::ForCurrentProcess());
95 bool ran_at_least_once = false;
96 std::unique_ptr<content::TestInfo> test_info;
97 while ((test_info = test_extractor.GetNextTest())) {
98 ran_at_least_once = true;
99 if (!RunOneTest(*test_info, &test_controller, main_runner))
100 break;
101 }
102 if (!ran_at_least_once) {
103 // CloseAllWindows will cause the |main_runner| loop to quit.
104 base::ThreadTaskRunnerHandle::Get()->PostTask(
105 FROM_HERE, base::BindOnce(&content::Shell::CloseAllWindows));
106 main_runner->Run();
107 }
108 }
109
110 } // namespace
111
Initialize()112 void WebTestBrowserMainRunner::Initialize() {
113 #if defined(OS_WIN)
114 bool layout_system_deps_ok = content::WebTestBrowserCheckLayoutSystemDeps();
115 CHECK(layout_system_deps_ok);
116 #endif
117
118 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
119
120 CHECK(browser_context_path_for_web_tests_.CreateUniqueTempDir());
121 CHECK(!browser_context_path_for_web_tests_.GetPath().MaybeAsASCII().empty());
122 command_line.AppendSwitchASCII(
123 switches::kContentShellDataPath,
124 browser_context_path_for_web_tests_.GetPath().MaybeAsASCII());
125
126 command_line.AppendSwitch(switches::kIgnoreCertificateErrors);
127
128 // Disable occlusion tracking. In a headless shell WebContents would always
129 // behave as if they were occluded, i.e. would not render frames and would
130 // not receive input events. For non-headless mode we do not want tests
131 // running in parallel to trigger occlusion tracking.
132 command_line.AppendSwitch(
133 switches::kDisableBackgroundingOccludedWindowsForTesting);
134
135 // Always disable the unsandbox GPU process for DX12 Info collection to avoid
136 // interference. This GPU process is launched 120 seconds after chrome starts.
137 command_line.AppendSwitch(switches::kDisableGpuProcessForDX12InfoCollection);
138
139 #if BUILDFLAG(ENABLE_PLUGINS)
140 bool ppapi_ok = ppapi::RegisterBlinkTestPlugin(&command_line);
141 CHECK(ppapi_ok);
142 #endif
143
144 command_line.AppendSwitch(cc::switches::kEnableGpuBenchmarking);
145 command_line.AppendSwitch(switches::kEnableLogging);
146 command_line.AppendSwitch(switches::kAllowFileAccessFromFiles);
147 // only default to a software GL if the flag isn't already specified.
148 if (!command_line.HasSwitch(switches::kUseGpuInTests) &&
149 !command_line.HasSwitch(switches::kUseGL)) {
150 command_line.AppendSwitchASCII(
151 switches::kUseGL,
152 gl::GetGLImplementationName(gl::GetSoftwareGLImplementation()));
153 }
154 command_line.AppendSwitchASCII(switches::kTouchEventFeatureDetection,
155 switches::kTouchEventFeatureDetectionEnabled);
156 if (!command_line.HasSwitch(switches::kForceDeviceScaleFactor))
157 command_line.AppendSwitchASCII(switches::kForceDeviceScaleFactor, "1.0");
158
159 if (!command_line.HasSwitch(switches::kAutoplayPolicy)) {
160 command_line.AppendSwitchASCII(
161 switches::kAutoplayPolicy,
162 switches::autoplay::kNoUserGestureRequiredPolicy);
163 }
164
165 if (!command_line.HasSwitch(switches::kStableReleaseMode)) {
166 command_line.AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
167 command_line.AppendSwitch(switches::kEnableBlinkTestFeatures);
168 }
169
170 if (!command_line.HasSwitch(switches::kEnableThreadedCompositing)) {
171 command_line.AppendSwitch(switches::kDisableThreadedCompositing);
172 command_line.AppendSwitch(cc::switches::kDisableThreadedAnimation);
173 }
174
175 // With display compositor pixel dumps, we ensure that we complete all
176 // stages of compositing before draw. We also can't have checker imaging,
177 // since it's incompatible with single threaded compositor and display
178 // compositor pixel dumps.
179 //
180 // TODO(crbug.com/894613) Add kRunAllCompositorStagesBeforeDraw back here
181 // once you figure out why it causes so much web test flakiness.
182 // command_line.AppendSwitch(switches::kRunAllCompositorStagesBeforeDraw);
183 command_line.AppendSwitch(cc::switches::kDisableCheckerImaging);
184
185 command_line.AppendSwitch(switches::kMuteAudio);
186
187 command_line.AppendSwitch(switches::kEnablePreciseMemoryInfo);
188
189 command_line.AppendSwitchASCII(network::switches::kHostResolverRules,
190 "MAP nonexistent.*.test ~NOTFOUND,"
191 "MAP *.test. 127.0.0.1,"
192 "MAP *.test 127.0.0.1");
193
194 // We want to know determanistically from command line flags if the Gpu
195 // process will provide gpu raster in its capabilities or not.
196 //
197 // If kEnableGpuRasterization is specified, the Gpu process always reports
198 // that it can gpu raster, and the renderer will use it. Otherwise, we don't
199 // want to choose at runtime, and we ensure that gpu raster is disabled.
200 if (!command_line.HasSwitch(switches::kEnableGpuRasterization))
201 command_line.AppendSwitch(switches::kDisableGpuRasterization);
202
203 // If the virtual test suite didn't specify a display color space, then
204 // force sRGB.
205 if (!command_line.HasSwitch(switches::kForceDisplayColorProfile))
206 command_line.AppendSwitchASCII(switches::kForceDisplayColorProfile, "srgb");
207
208 // We want stable/baseline results when running web tests.
209 command_line.AppendSwitch(switches::kDisableSkiaRuntimeOpts);
210
211 command_line.AppendSwitch(switches::kDisallowNonExactResourceReuse);
212
213 // Always run with fake media devices.
214 command_line.AppendSwitch(switches::kUseFakeUIForMediaStream);
215 command_line.AppendSwitch(switches::kUseFakeDeviceForMediaStream);
216
217 // Enable the deprecated WebAuthn Mojo Testing API.
218 command_line.AppendSwitch(switches::kEnableWebAuthDeprecatedMojoTestingApi);
219
220 // Always disable the unsandbox GPU process for DX12 Info collection to avoid
221 // interference. This GPU process is launched 120 seconds after chrome starts.
222 command_line.AppendSwitch(switches::kDisableGpuProcessForDX12InfoCollection);
223
224 #if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \
225 defined(OS_CHROMEOS)
226 content::WebTestBrowserPlatformInitialize();
227 #endif
228
229 RenderWidgetHostImpl::DisableResizeAckCheckForTesting();
230 }
231
RunBrowserMain(const content::MainFunctionParams & parameters)232 void WebTestBrowserMainRunner::RunBrowserMain(
233 const content::MainFunctionParams& parameters) {
234 std::unique_ptr<content::BrowserMainRunner> main_runner =
235 content::BrowserMainRunner::Create();
236 int initialize_exit_code = main_runner->Initialize(parameters);
237 DCHECK_LT(initialize_exit_code, 0)
238 << "BrowserMainRunner::Initialize failed in WebTestBrowserMainRunner";
239
240 RunTests(main_runner.get());
241 base::RunLoop().RunUntilIdle();
242
243 content::Shell::CloseAllWindows();
244
245 main_runner->Shutdown();
246 }
247
248 } // namespace content
249