diff options
Diffstat (limited to 'onionshare_gui/mode/__init__.py')
-rw-r--r-- | onionshare_gui/mode/__init__.py | 126 |
1 files changed, 104 insertions, 22 deletions
diff --git a/onionshare_gui/mode/__init__.py b/onionshare_gui/mode/__init__.py index 4fe335e7..8f5ff32b 100644 --- a/onionshare_gui/mode/__init__.py +++ b/onionshare_gui/mode/__init__.py @@ -20,10 +20,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. from PyQt5 import QtCore, QtWidgets, QtGui from onionshare import strings -from onionshare.common import ShutdownTimer +from onionshare.common import AutoStopTimer from ..server_status import ServerStatus from ..threads import OnionThread +from ..threads import AutoStartTimer from ..widgets import Alert class Mode(QtWidgets.QWidget): @@ -35,6 +36,7 @@ class Mode(QtWidgets.QWidget): starting_server_step2 = QtCore.pyqtSignal() starting_server_step3 = QtCore.pyqtSignal() starting_server_error = QtCore.pyqtSignal(str) + starting_server_early = QtCore.pyqtSignal() set_server_active = QtCore.pyqtSignal(bool) def __init__(self, common, qtapp, app, status_bar, server_status_label, system_tray, filenames=None, local_only=False): @@ -58,6 +60,7 @@ class Mode(QtWidgets.QWidget): # Threads start out as None self.onion_thread = None self.web_thread = None + self.startup_thread = None # Server status self.server_status = ServerStatus(self.common, self.qtapp, self.app, None, self.local_only) @@ -68,6 +71,7 @@ class Mode(QtWidgets.QWidget): self.stop_server_finished.connect(self.server_status.stop_server_finished) self.starting_server_step2.connect(self.start_server_step2) self.starting_server_step3.connect(self.start_server_step3) + self.starting_server_early.connect(self.start_server_early) self.starting_server_error.connect(self.start_server_error) # Primary action @@ -88,24 +92,55 @@ class Mode(QtWidgets.QWidget): """ pass + def human_friendly_time(self, secs): + """ + Returns a human-friendly time delta from given seconds. + """ + days = secs//86400 + hours = (secs - days*86400)//3600 + minutes = (secs - days*86400 - hours*3600)//60 + seconds = secs - days*86400 - hours*3600 - minutes*60 + if not seconds: + seconds = '0' + result = ("{0}{1}, ".format(days, strings._('days_first_letter')) if days else "") + \ + ("{0}{1}, ".format(hours, strings._('hours_first_letter')) if hours else "") + \ + ("{0}{1}, ".format(minutes, strings._('minutes_first_letter')) if minutes else "") + \ + "{0}{1}".format(seconds, strings._('seconds_first_letter')) + + return result + def timer_callback(self): """ This method is called regularly on a timer. """ - # If the auto-shutdown timer has stopped, stop the server + # If this is a scheduled share, display the countdown til the share starts + if self.server_status.status == ServerStatus.STATUS_WORKING: + if self.server_status.autostart_timer_datetime: + now = QtCore.QDateTime.currentDateTime() + if self.server_status.local_only: + seconds_remaining = now.secsTo(self.server_status.autostart_timer_widget.dateTime()) + else: + seconds_remaining = now.secsTo(self.server_status.autostart_timer_datetime.replace(second=0, microsecond=0)) + # Update the server button + if seconds_remaining > 0: + self.server_status.server_button.setText(strings._('gui_waiting_to_start').format(self.human_friendly_time(seconds_remaining))) + else: + self.server_status.server_button.setText(strings._('gui_please_wait')) + + # If the auto-stop timer has stopped, stop the server if self.server_status.status == ServerStatus.STATUS_STARTED: - if self.app.shutdown_timer and self.common.settings.get('shutdown_timeout'): - if self.timeout > 0: + if self.app.autostop_timer_thread and self.common.settings.get('autostop_timer'): + if self.autostop_timer_datetime_delta > 0: now = QtCore.QDateTime.currentDateTime() - seconds_remaining = now.secsTo(self.server_status.timeout) + seconds_remaining = now.secsTo(self.server_status.autostop_timer_datetime) # Update the server button - server_button_text = self.get_stop_server_shutdown_timeout_text() - self.server_status.server_button.setText(server_button_text.format(seconds_remaining)) + server_button_text = self.get_stop_server_autostop_timer_text() + self.server_status.server_button.setText(server_button_text.format(self.human_friendly_time(seconds_remaining))) self.status_bar.clearMessage() - if not self.app.shutdown_timer.is_alive(): - if self.timeout_finished_should_stop_server(): + if not self.app.autostop_timer_thread.is_alive(): + if self.autostop_timer_finished_should_stop_server(): self.server_status.stop_server() def timer_callback_custom(self): @@ -114,15 +149,15 @@ class Mode(QtWidgets.QWidget): """ pass - def get_stop_server_shutdown_timeout_text(self): + def get_stop_server_autostop_timer_text(self): """ - Return the string to put on the stop server button, if there's a shutdown timeout + Return the string to put on the stop server button, if there's an auto-stop timer """ pass - def timeout_finished_should_stop_server(self): + def autostop_timer_finished_should_stop_server(self): """ - The shutdown timer expired, should we stop the server? Returns a bool + The auto-stop timer expired, should we stop the server? Returns a bool """ pass @@ -142,7 +177,41 @@ class Mode(QtWidgets.QWidget): self.status_bar.clearMessage() self.server_status_label.setText('') + # Ensure we always get a new random port each time we might launch an OnionThread + self.app.port = None + + # Start the onion thread. If this share was scheduled for a future date, + # the OnionThread will start and exit 'early' to obtain the port, slug + # and onion address, but it will not start the WebThread yet. + if self.server_status.autostart_timer_datetime: + self.start_onion_thread(obtain_onion_early=True) + else: + self.start_onion_thread() + + # If scheduling a share, delay starting the real share + if self.server_status.autostart_timer_datetime: + self.common.log('Mode', 'start_server', 'Starting auto-start timer') + self.startup_thread = AutoStartTimer(self) + # Once the timer has finished, start the real share, with a WebThread + self.startup_thread.success.connect(self.start_scheduled_service) + self.startup_thread.error.connect(self.start_server_error) + self.startup_thread.canceled = False + self.startup_thread.start() + + def start_onion_thread(self, obtain_onion_early=False): self.common.log('Mode', 'start_server', 'Starting an onion thread') + self.obtain_onion_early = obtain_onion_early + self.onion_thread = OnionThread(self) + self.onion_thread.success.connect(self.starting_server_step2.emit) + self.onion_thread.success_early.connect(self.starting_server_early.emit) + self.onion_thread.error.connect(self.starting_server_error.emit) + self.onion_thread.start() + + def start_scheduled_service(self, obtain_onion_early=False): + # We start a new OnionThread with the saved scheduled key from settings + self.common.settings.load() + self.obtain_onion_early = obtain_onion_early + self.common.log('Mode', 'start_server', 'Starting a scheduled onion thread') self.onion_thread = OnionThread(self) self.onion_thread.success.connect(self.starting_server_step2.emit) self.onion_thread.error.connect(self.starting_server_error.emit) @@ -154,6 +223,14 @@ class Mode(QtWidgets.QWidget): """ pass + def start_server_early(self): + """ + An 'early' start of an onion service in order to obtain the onion + address for a scheduled start. Shows the onion address in the UI + in advance of actually starting the share. + """ + self.server_status.show_url() + def start_server_step2(self): """ Step 2 in starting the onionshare server. @@ -182,18 +259,18 @@ class Mode(QtWidgets.QWidget): self.start_server_step3_custom() - if self.common.settings.get('shutdown_timeout'): + if self.common.settings.get('autostop_timer'): # Convert the date value to seconds between now and then now = QtCore.QDateTime.currentDateTime() - self.timeout = now.secsTo(self.server_status.timeout) - # Set the shutdown timeout value - if self.timeout > 0: - self.app.shutdown_timer = ShutdownTimer(self.common, self.timeout) - self.app.shutdown_timer.start() - # The timeout has actually already passed since the user clicked Start. Probably the Onion service took too long to start. + self.autostop_timer_datetime_delta = now.secsTo(self.server_status.autostop_timer_datetime) + # Start the auto-stop timer + if self.autostop_timer_datetime_delta > 0: + self.app.autostop_timer_thread = AutoStopTimer(self.common, self.autostop_timer_datetime_delta) + self.app.autostop_timer_thread.start() + # The auto-stop timer has actually already passed since the user clicked Start. Probably the Onion service took too long to start. else: self.stop_server() - self.start_server_error(strings._('gui_server_started_after_timeout')) + self.start_server_error(strings._('gui_server_started_after_autostop_timer')) def start_server_step3_custom(self): """ @@ -225,7 +302,12 @@ class Mode(QtWidgets.QWidget): Cancel the server while it is preparing to start """ self.cancel_server_custom() - + if self.startup_thread: + self.common.log('Mode', 'cancel_server: quitting startup thread') + self.startup_thread.canceled = True + self.app.onion.scheduled_key = None + self.app.onion.scheduled_auth_cookie = None + self.startup_thread.quit() if self.onion_thread: self.common.log('Mode', 'cancel_server: quitting onion thread') self.onion_thread.quit() |