1 ASP_STATE_DIR = '/run/live-additional-software'.freeze
2 ASP_CONF = '/live/persistence/TailsData_unlocked/live-additional-software.conf'
5 Then /^the Additional Software (upgrade|installation) service has started$/ do |service|
6 if $vm.file_exist?(ASP_CONF) && !$vm.file_empty?(ASP_CONF)
9 service_name = 'tails-additional-software-install.service'
12 service_name = 'tails-additional-software-upgrade.service'
15 try_for(seconds_to_wait, delay: 10) do
16 $vm.execute("systemctl status #{service_name}").success?
21 Then /^I am notified I can not use Additional Software for "([^"]*)"$/ do |package|
22 title = "You could install #{package} automatically when starting Tails"
23 step "I see the \"#{title}\" notification after at most 300 seconds"
26 Then /^I am notified that the installation succeeded$/ do
27 title = 'Additional software installed successfully'
28 step "I see the \"#{title}\" notification after at most 300 seconds"
31 Then /^I am proposed to add the "([^"]*)" package to my Additional Software$/ do |package|
32 title = "Add #{package} to your additional software?"
33 step "I see the \"#{title}\" notification after at most 300 seconds"
36 def click_gnome_shell_notification_button(title)
37 # The notification buttons do not expose any actions through AT-SPI,
38 # so Dogtail is unable to click it directly. We let it grab focus
39 # and activate it via the keyboard instead.
40 Dogtail::Application.new('gnome-shell')
41 .child(title, roleName: 'push button')
43 @screen.press('Return')
46 Then /^I create a persistent storage and activate the Additional Software feature$/ do
47 click_gnome_shell_notification_button('Create Persistent Storage')
48 step 'I create a persistent partition for Additional Software'
49 assert_additional_software_persistent_storage_feature_is_enabled
52 def assert_additional_software_persistent_storage_feature_is_enabled
53 assert persistent_storage_main_frame.child('Personal Documents', roleName: 'label')
54 additional_software_switch = persistent_storage_main_frame.child(
55 'Activate Additional Software',
56 roleName: 'toggle button'
58 assert additional_software_switch.checked
61 Then /^Additional Software is correctly configured for package "([^"]*)"$/ do |package|
63 assert($vm.file_exist?(ASP_CONF), 'ASP configuration file not found')
64 step 'all persistence configuration files have safe access rights'
67 "/live/persistence/TailsData_unlocked/apt/cache/#{package}_*.deb"
71 $vm.file_glob('/live/persistence/TailsData_unlocked/apt/lists/*_Packages')
74 "grep --line-regexp --fixed-strings #{package} #{ASP_CONF}"
79 Then /^"([^"]*)" is not in the list of Additional Software$/ do |package|
80 assert($vm.file_exist?(ASP_CONF), 'ASP configuration file not found')
81 step 'all persistence configuration files have safe access rights'
83 $vm.execute("grep \"#{package}\" #{ASP_CONF}").stdout.empty?
87 When /^I (refuse|accept) (adding|removing) "(?:[^"]*)" (?:to|from) Additional Software$/ do |decision, action|
92 button_title = 'Install Every Time'
94 button_title = 'Install Only Once'
99 button_title = 'Remove'
101 button_title = 'Cancel'
105 click_gnome_shell_notification_button(button_title)
110 Given /^I remove "([^"]*)" from the list of Additional Software using Additional Software GUI$/ do |package|
111 asp_gui = Dogtail::Application.new('tails-additional-software-config')
112 installed_package = asp_gui.child(package, roleName: 'label')
113 # We can't use the click action here because this button causes a
114 # modal dialog to be run via gtk_dialog_run() which causes the
115 # application to hang when triggered via a ATSPI action. See
116 # https://gitlab.gnome.org/GNOME/gtk/-/issues/1281
117 installed_package.parent.parent.child('Remove', roleName: 'push button').grabFocus
118 @screen.press('Return')
119 asp_gui.child('Question', roleName: 'alert').button('Remove').click
120 deal_with_polkit_prompt(@sudo_password)
123 When /^I prepare the Additional Software upgrade process to fail$/ do
124 # Remove the newest cowsay package from the APT cache with a DPKG hook
125 # before it gets upgraded so that we simulate a failing upgrade.
126 failing_dpkg_hook = <<~HOOK
128 "ls -1 -v /var/cache/apt/archives/cowsay*.deb | tail -n 1 | xargs rm";
131 $vm.file_overwrite('/etc/apt/apt.conf.d/00failingDPKGhook', failing_dpkg_hook)
132 # Tell the upgrade service check step not to run
133 $vm.execute_successfully("touch #{ASP_STATE_DIR}/doomed_to_fail")
136 When /^I remove the "([^"]*)" deb files from the APT cache$/ do |package|
137 $vm.execute_successfully(
138 "rm /live/persistence/TailsData_unlocked/apt/cache/#{package}_*.deb"
142 Then /^I can open the Additional Software documentation from the notification$/ do
143 click_gnome_shell_notification_button('Documentation')
144 try_for(60) { @torbrowser = Dogtail::Application.new('Firefox') }
145 step '"Tails - Install by cloning" has loaded in the Tor Browser'
148 Then /^the Additional Software dpkg hook has been run for package "([^"]*)" and notices the persistence is locked$/ do |package|
149 asp_logs = "#{ASP_STATE_DIR}/log"
150 assert(!$vm.file_empty?(asp_logs))
151 try_for(180, delay: 2) do
153 "grep -E '^.*New\spackages\smanually\sinstalled:\s.*#{package}.*$' " \
158 $vm.file_content(asp_logs)
159 .include?('Warning: persistence storage is locked')
163 When /^I can open the Additional Software configuration window from the notification$/ do
164 click_gnome_shell_notification_button('Configure')
165 Dogtail::Application.new('tails-additional-software-config')
168 Then /^I can open the Additional Software log file from the notification$/ do
169 click_gnome_shell_notification_button('Show Log')
171 Dogtail::Application.new('gnome-text-editor').child(
172 "log (#{ASP_STATE_DIR}) - Text Editor", roleName: 'frame'