1{ system ? builtins.currentSystem
2, config ? {}
3, pkgs ? import ../.. { inherit system config; }
4, channelMap ? { # Maps "channels" to packages
5 stable = pkgs.chromium;
6 beta = pkgs.chromiumBeta;
7 dev = pkgs.chromiumDev;
8 ungoogled = pkgs.ungoogled-chromium;
9 chrome-stable = pkgs.google-chrome;
10 chrome-beta = pkgs.google-chrome-beta;
11 chrome-dev = pkgs.google-chrome-dev;
12 }
13}:
14
15with import ../lib/testing-python.nix { inherit system pkgs; };
16with pkgs.lib;
17
18mapAttrs (channel: chromiumPkg: makeTest rec {
19 name = "chromium-${channel}";
20 meta = {
21 maintainers = with maintainers; [ aszlig primeos ];
22 # https://github.com/NixOS/hydra/issues/591#issuecomment-435125621
23 inherit (chromiumPkg.meta) timeout;
24 };
25
26 enableOCR = true;
27
28 user = "alice";
29
30 machine.imports = [ ./common/user-account.nix ./common/x11.nix ];
31 machine.virtualisation.memorySize = 2047;
32 machine.test-support.displayManager.auto.user = user;
33 machine.environment = {
34 systemPackages = [ chromiumPkg ];
35 variables."XAUTHORITY" = "/home/alice/.Xauthority";
36 };
37
38 startupHTML = pkgs.writeText "chromium-startup.html" ''
39 <!DOCTYPE html>
40 <html>
41 <head>
42 <meta charset="UTF-8">
43 <title>Chromium startup notifier</title>
44 </head>
45 <body onload="javascript:document.title='startup done'">
46 <img src="file://${pkgs.fetchurl {
47 url = "https://nixos.org/logo/nixos-hex.svg";
48 sha256 = "07ymq6nw8kc22m7kzxjxldhiq8gzmc7f45kq2bvhbdm0w5s112s4";
49 }}" />
50 </body>
51 </html>
52 '';
53
54 testScript = let
55 xdo = name: text: let
56 xdoScript = pkgs.writeText "${name}.xdo" text;
57 in "${pkgs.xdotool}/bin/xdotool ${xdoScript}";
58 in ''
59 import shlex
60 import re
61 from contextlib import contextmanager
62
63
64 # Run as user alice
65 def ru(cmd):
66 return "su - ${user} -c " + shlex.quote(cmd)
67
68
69 def launch_browser():
70 """Launches the web browser with the correct options."""
71 # Determine the name of the binary:
72 pname = "${getName chromiumPkg.name}"
73 if pname.find("chromium") != -1:
74 binary = "chromium" # Same name for all channels and ungoogled-chromium
75 elif pname == "google-chrome":
76 binary = "google-chrome-stable"
77 elif pname == "google-chrome-dev":
78 binary = "google-chrome-unstable"
79 else: # For google-chrome-beta and as fallback:
80 binary = pname
81 # Add optional CLI options:
82 options = []
83 major_version = "${versions.major (getVersion chromiumPkg.name)}"
84 if major_version > "95" and not pname.startswith("google-chrome"):
85 # Workaround to avoid a GPU crash:
86 options.append("--use-gl=swiftshader")
87 # Launch the process:
88 options.append("file://${startupHTML}")
89 machine.succeed(ru(f'ulimit -c unlimited; {binary} {shlex.join(options)} >&2 & disown'))
90 if binary.startswith("google-chrome"):
91 # Need to click away the first window:
92 machine.wait_for_text("Make Google Chrome the default browser")
93 machine.screenshot("google_chrome_default_browser_prompt")
94 machine.send_key("ret")
95
96
97 def create_new_win():
98 """Creates a new Chromium window."""
99 with machine.nested("Creating a new Chromium window"):
100 machine.wait_until_succeeds(
101 ru(
102 "${xdo "create_new_win-select_main_window" ''
103 search --onlyvisible --name "startup done"
104 windowfocus --sync
105 windowactivate --sync
106 ''}"
107 )
108 )
109 machine.send_key("ctrl-n")
110 # Wait until the new window appears:
111 machine.wait_until_succeeds(
112 ru(
113 "${xdo "create_new_win-wait_for_window" ''
114 search --onlyvisible --name "New Tab"
115 windowfocus --sync
116 windowactivate --sync
117 ''}"
118 )
119 )
120
121
122 def close_new_tab_win():
123 """Closes the Chromium window with the title "New Tab"."""
124 machine.wait_until_succeeds(
125 ru(
126 "${xdo "close_new_tab_win-select_main_window" ''
127 search --onlyvisible --name "New Tab"
128 windowfocus --sync
129 windowactivate --sync
130 ''}"
131 )
132 )
133 machine.send_key("ctrl-w")
134 # Wait until the closed window disappears:
135 machine.wait_until_fails(
136 ru(
137 "${xdo "close_new_tab_win-wait_for_close" ''
138 search --onlyvisible --name "New Tab"
139 ''}"
140 )
141 )
142
143
144 @contextmanager
145 def test_new_win(description, url, window_name):
146 create_new_win()
147 machine.wait_for_window("New Tab")
148 machine.send_chars(f"{url}\n")
149 machine.wait_for_window(window_name)
150 machine.screenshot(description)
151 machine.succeed(
152 ru(
153 "${xdo "copy-all" ''
154 key --delay 1000 Ctrl+a Ctrl+c
155 ''}"
156 )
157 )
158 clipboard = machine.succeed(
159 ru("${pkgs.xclip}/bin/xclip -o")
160 )
161 print(f"{description} window content:\n{clipboard}")
162 with machine.nested(description):
163 yield clipboard
164 # Close the newly created window:
165 machine.send_key("ctrl-w")
166
167
168 machine.wait_for_x()
169
170 launch_browser()
171
172 machine.wait_for_text("startup done")
173 machine.wait_until_succeeds(
174 ru(
175 "${xdo "check-startup" ''
176 search --sync --onlyvisible --name "startup done"
177 # close first start help popup
178 key -delay 1000 Escape
179 windowfocus --sync
180 windowactivate --sync
181 ''}"
182 )
183 )
184
185 create_new_win()
186 # Optional: Wait for the new tab page to fully load before taking the screenshot:
187 machine.wait_for_text("Web Store")
188 machine.screenshot("empty_windows")
189 close_new_tab_win()
190
191 machine.screenshot("startup_done")
192
193 with test_new_win("sandbox_info", "chrome://sandbox", "Sandbox Status") as clipboard:
194 filters = [
195 "layer 1 sandbox.*namespace",
196 "pid namespaces.*yes",
197 "network namespaces.*yes",
198 "seccomp.*sandbox.*yes",
199 "you are adequately sandboxed",
200 ]
201 if not all(
202 re.search(filter, clipboard, flags=re.DOTALL | re.IGNORECASE)
203 for filter in filters
204 ):
205 assert False, f"sandbox not working properly: {clipboard}"
206
207 machine.sleep(1)
208 machine.succeed(
209 ru(
210 "${xdo "find-window-after-copy" ''
211 search --onlyvisible --name "Sandbox Status"
212 ''}"
213 )
214 )
215
216 clipboard = machine.succeed(
217 ru(
218 "echo void | ${pkgs.xclip}/bin/xclip -i >&2"
219 )
220 )
221 machine.succeed(
222 ru(
223 "${xdo "copy-sandbox-info" ''
224 key --delay 1000 Ctrl+a Ctrl+c
225 ''}"
226 )
227 )
228
229 clipboard = machine.succeed(
230 ru("${pkgs.xclip}/bin/xclip -o")
231 )
232 if not all(
233 re.search(filter, clipboard, flags=re.DOTALL | re.IGNORECASE)
234 for filter in filters
235 ):
236 assert False, f"copying twice in a row does not work properly: {clipboard}"
237
238 machine.screenshot("after_copy_from_chromium")
239
240
241 with test_new_win("gpu_info", "chrome://gpu", "chrome://gpu"):
242 # To check the text rendering (catches regressions like #131074):
243 machine.wait_for_text("Graphics Feature Status")
244
245
246 with test_new_win("version_info", "chrome://version", "About Version") as clipboard:
247 filters = [
248 r"${chromiumPkg.version} \(Official Build",
249 ]
250 if not all(
251 re.search(filter, clipboard) for filter in filters
252 ):
253 assert False, "Version info not correct."
254
255
256 machine.shutdown()
257 '';
258}) channelMap