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