Merge pull request #1236 from micahflee/929_download_errors

Prevent incomplete downloads in share mode, close after first download
This commit is contained in:
Micah Lee 2020-12-15 16:45:58 -08:00 committed by GitHub
commit 5200f8714a
14 changed files with 141 additions and 18 deletions

View file

@ -30,6 +30,7 @@ from .widgets import Alert
from .update_checker import UpdateThread
from .tab_widget import TabWidget
from .gui_common import GuiCommon
from .threads import OnionCleanupThread
class MainWindow(QtWidgets.QMainWindow):
@ -285,8 +286,32 @@ class MainWindow(QtWidgets.QMainWindow):
e.accept()
def cleanup(self):
self.common.log("MainWindow", "cleanup")
self.tabs.cleanup()
self.common.gui.onion.cleanup()
alert = Alert(
self.common,
strings._("gui_rendezvous_cleanup"),
QtWidgets.QMessageBox.Information,
buttons=QtWidgets.QMessageBox.NoButton,
autostart=False,
)
quit_early_button = QtWidgets.QPushButton(
strings._("gui_rendezvous_cleanup_quit_early")
)
alert.addButton(quit_early_button, QtWidgets.QMessageBox.RejectRole)
self.onion_cleanup_thread = OnionCleanupThread(self.common)
self.onion_cleanup_thread.finished.connect(alert.accept)
self.onion_cleanup_thread.start()
alert.exec_()
if alert.clickedButton() == quit_early_button:
self.common.log("MainWindow", "cleanup", "quitting early")
if self.onion_cleanup_thread.isRunning():
self.onion_cleanup_thread.terminate()
self.onion_cleanup_thread.wait()
self.common.gui.onion.cleanup(wait=False)
# Wait 1 second for threads to close gracefully, so tests finally pass
time.sleep(1)

View file

@ -188,5 +188,7 @@
"settings_error_bundled_tor_not_supported": "Using the Tor version that comes with OnionShare does not work in developer mode on Windows or macOS.",
"settings_error_bundled_tor_timeout": "Taking too long to connect to Tor. Maybe you aren't connected to the Internet, or have an inaccurate system clock?",
"settings_error_bundled_tor_broken": "OnionShare could not connect to Tor:\n{}",
"gui_rendezvous_cleanup": "Waiting for Tor circuits to close to be sure your files have successfully transferred.\n\nThis might take a few minutes.",
"gui_rendezvous_cleanup_quit_early": "Quit Early",
"error_port_not_available": "OnionShare port not available"
}

View file

@ -107,6 +107,12 @@ class Mode(QtWidgets.QWidget):
"""
pass
def get_type(self):
"""
Returns the type of mode as a string (e.g. "share", "receive", etc.)
"""
pass
def human_friendly_time(self, secs):
"""
Returns a human-friendly time delta from given seconds.

View file

@ -101,6 +101,12 @@ class ChatMode(Mode):
self.wrapper_layout.addLayout(self.column_layout)
self.setLayout(self.wrapper_layout)
def get_type(self):
"""
Returns the type of mode as a string (e.g. "share", "receive", etc.)
"""
return "chat"
def get_stop_server_autostop_timer_text(self):
"""
Return the string to put on the stop server button, if there's an auto-stop timer

View file

@ -149,6 +149,12 @@ class ReceiveMode(Mode):
self.wrapper_layout.addLayout(self.column_layout)
self.setLayout(self.wrapper_layout)
def get_type(self):
"""
Returns the type of mode as a string (e.g. "share", "receive", etc.)
"""
return "receive"
def data_dir_button_clicked(self):
"""
Browse for a new OnionShare data directory, and save to tab settings

View file

@ -173,6 +173,12 @@ class ShareMode(Mode):
# Always start with focus on file selection
self.file_selection.setFocus()
def get_type(self):
"""
Returns the type of mode as a string (e.g. "share", "receive", etc.)
"""
return "share"
def autostop_sharing_checkbox_clicked(self):
"""
Save autostop sharing setting to the tab settings

View file

@ -173,6 +173,12 @@ class WebsiteMode(Mode):
# Always start with focus on file selection
self.file_selection.setFocus()
def get_type(self):
"""
Returns the type of mode as a string (e.g. "share", "receive", etc.)
"""
return "website"
def disable_csp_checkbox_clicked(self):
"""
Save disable CSP setting to the tab settings

View file

@ -669,7 +669,9 @@ class Tab(QtWidgets.QWidget):
return False
def cleanup(self):
self.common.log("Tab", "cleanup", f"tab_id={self.tab_id}")
if self.get_mode() and self.get_mode().web_thread:
self.get_mode().web.stop(self.get_mode().app.port)
self.get_mode().web_thread.quit()
self.get_mode().web_thread.wait()
self.app.cleanup()

View file

@ -81,6 +81,8 @@ class TabWidget(QtWidgets.QTabWidget):
self.event_handler_t.start()
def cleanup(self):
self.common.log("TabWidget", "cleanup")
# Stop the event thread
self.event_handler_t.should_quit = True
self.event_handler_t.quit()

View file

@ -77,7 +77,7 @@ class OnionThread(QtCore.QThread):
try:
if self.mode.obtain_onion_early:
self.mode.app.start_onion_service(
self.mode.settings, await_publication=False
self.mode.get_type(), self.mode.settings, await_publication=False
)
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash
time.sleep(0.2)
@ -86,7 +86,7 @@ class OnionThread(QtCore.QThread):
self.mode.app.stop_onion_service(self.mode.settings)
else:
self.mode.app.start_onion_service(
self.mode.settings, await_publication=True
self.mode.get_type(), self.mode.settings, await_publication=True
)
# wait for modules in thread to load, preventing a thread-related cx_Freeze crash
time.sleep(0.2)
@ -258,3 +258,18 @@ class EventHandlerThread(QtCore.QThread):
if self.should_quit:
break
time.sleep(0.2)
class OnionCleanupThread(QtCore.QThread):
"""
Wait for Tor rendezvous circuits to close in a separate thread
"""
def __init__(self, common):
super(OnionCleanupThread, self).__init__()
self.common = common
self.common.log("OnionCleanupThread", "__init__")
def run(self):
self.common.log("OnionCleanupThread", "run")
self.common.gui.onion.cleanup()