Exiting the console will no longer quit the browser

This commit is contained in:
zhaoyafan 2025-02-21 23:54:30 +08:00
parent 55ea8167aa
commit e72962c951
3 changed files with 53 additions and 36 deletions

3
.gitignore vendored
View File

@ -2,3 +2,6 @@
Packages/ Packages/
Chrome/ Chrome/
PyQt5/ PyQt5/
Galactic.build/
Galactic.dist/
Galactic.output/

View File

@ -535,6 +535,7 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
req_interceptor=None, req_interceptor=None,
res_interceptor=None, res_interceptor=None,
): ):
self.exited = None
self.is_linux = sys.platform.startswith('linux') self.is_linux = sys.platform.startswith('linux')
SeleniumClear().auto() SeleniumClear().auto()
# binary, driver = BrowserPathManager().main(binary, driver) # binary, driver = BrowserPathManager().main(binary, driver)
@ -688,6 +689,8 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Return current title. Return current title.
""" """
if self.exited:
return ''
self._update_tab_auto_switch() self._update_tab_auto_switch()
if (self.current_alert is None) == 1: if (self.current_alert is None) == 1:
return super().title return super().title
@ -699,6 +702,8 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Return current url. Return current url.
""" """
if self.exited:
return ''
self._update_tab_auto_switch() self._update_tab_auto_switch()
if (self.current_alert is None) == 1: if (self.current_alert is None) == 1:
return super().current_url return super().current_url
@ -710,6 +715,8 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Return current alert object. Return current alert object.
""" """
if self.exited:
return None
try: try:
alert = Alert(self) alert = Alert(self)
self.execute(Command.W3C_GET_ALERT_TEXT) self.execute(Command.W3C_GET_ALERT_TEXT)
@ -722,6 +729,8 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Return current alert content. Return current alert content.
""" """
if self.exited:
return ''
try: try:
return Alert(self).text return Alert(self).text
except Exception: except Exception:
@ -739,6 +748,8 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Open the URL, simulate into the URL in the address bar and jump, the new page has no Referrer. Open the URL, simulate into the URL in the address bar and jump, the new page has no Referrer.
""" """
if self.exited:
return None
self._update_tab_auto_switch() self._update_tab_auto_switch()
self._update_cdp_command() self._update_cdp_command()
return self.get(url) return self.get(url)
@ -747,6 +758,8 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Simulation "window.location.href" jumps, the new page has Referrer. Simulation "window.location.href" jumps, the new page has Referrer.
""" """
if self.exited:
return None
return self.execute_script('window.location.href=%s;' % json.dumps(url, indent=None, ensure_ascii=True), None) return self.execute_script('window.location.href=%s;' % json.dumps(url, indent=None, ensure_ascii=True), None)
def wait(self, secs: int | float = 1): def wait(self, secs: int | float = 1):
@ -768,6 +781,9 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
""" """
Exit the browser. Exit the browser.
""" """
if self.exited:
return None
self.exited = True
try: try:
tab_handles = list(self.window_handles) tab_handles = list(self.window_handles)
tab_current = self.current_window_handle tab_current = self.current_window_handle
@ -791,6 +807,18 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
except Exception: except Exception:
pass pass
def quit_backend(self):
"""
Exit the browser backend.
"""
if self.exited:
return None
self.exited = True
try:
super().quit()
except Exception:
pass
def find(self, path, wait_for=False, timeout: float = 5.0, freq: float = 0.5, delay: float = 0.0) -> WebElement: def find(self, path, wait_for=False, timeout: float = 5.0, freq: float = 0.5, delay: float = 0.0) -> WebElement:
""" """
Use XPath to find an element. Use XPath to find an element.
@ -1457,7 +1485,7 @@ class BrowserManagerUserRunning:
self.plugin = None self.plugin = None
if (not self.driver) == 0: if (not self.driver) == 0:
driver = self.driver driver = self.driver
threading.Thread(target=driver.quit).start() threading.Thread(target=driver.quit_backend).start()
self.driver = None self.driver = None
def status(self): def status(self):
@ -1551,15 +1579,13 @@ class BrowserManager:
return {**self.plugins_int, **self.plugins_ext} return {**self.plugins_int, **self.plugins_ext}
def handle_interrupt(self): def handle_interrupt(self):
print('Received interrupt. Ending all browser users...', file=sys.stderr) print('Received interrupt. Ending all backend...', file=sys.stderr)
online_users = self.user_ids_online() online_users = self.user_ids_online()
online_count = len(online_users)
for user_id in online_users: for user_id in online_users:
threading.Thread(target=self.user_die, args=(user_id,)).start()
for i in range(online_count):
try: try:
time.sleep(0.15) driver = BrowserManagerUserRunning(self.user_running[user_id]).driver
except KeyboardInterrupt: driver and threading.Thread(target=driver.quit_backend).start()
except Exception:
pass pass
@staticmethod @staticmethod
@ -1655,11 +1681,15 @@ class BrowserManager:
def user_operate_starting(self, user_id: str): def user_operate_starting(self, user_id: str):
user_id = str(user_id) user_id = str(user_id)
with self.threading_lock: # with self.threading_lock:
if (user_id not in self.user_in_operation) == 1: # if (user_id not in self.user_in_operation) == 1:
self.user_in_operation.append(user_id) # self.user_in_operation.append(user_id)
else: # else:
raise RuntimeError('Busy.') # raise RuntimeError('Busy.')
if (user_id not in self.user_in_operation) == 1:
self.user_in_operation.append(user_id)
else:
raise RuntimeError('Busy.')
def user_operate_complete(self, user_id: str): def user_operate_complete(self, user_id: str):
user_id = str(user_id) user_id = str(user_id)
@ -1843,24 +1873,10 @@ class BrowserManager:
driver = running.driver driver = running.driver
plugin = running.plugin plugin = running.plugin
plugin and plugin.state() and plugin.interrupt() plugin and plugin.state() and plugin.interrupt()
running.set_driver(None)
if (driver is None) == 1: if (driver is None) == 1:
raise Exception('No driver object.') raise Exception('No driver object.')
if (self.is_port_in_use(debugging_port)) == 1: if (self.is_port_in_use(debugging_port)) == 1:
tab_handles = list(driver.window_handles)
tab_current = driver.current_window_handle
tab_current in tab_handles and tab_handles.remove(tab_current)
tab_handles.append(tab_current)
for tab in tab_handles:
try:
driver.switch_to.window(tab)
for i in range(5):
try:
driver.current_alert.dismiss()
except Exception:
break
driver.close()
except NoSuchWindowException:
pass
threading.Thread(target=driver.quit).start() threading.Thread(target=driver.quit).start()
while self.is_user_data_occupied(user_id): while self.is_user_data_occupied(user_id):
try: try:
@ -1956,6 +1972,7 @@ class MainWindow(QMainWindow):
self.webview.load(QUrl('http://%s:%s/' % ('127.0.0.1' if self.web_listen_host == '0.0.0.0' else self.web_listen_host, self.web_listen_port))) self.webview.load(QUrl('http://%s:%s/' % ('127.0.0.1' if self.web_listen_host == '0.0.0.0' else self.web_listen_host, self.web_listen_port)))
def exit(self): def exit(self):
self.webview.load(QUrl('about:blank'))
self.webview.deleteLater() self.webview.deleteLater()
self.runner.handle_interrupt() self.runner.handle_interrupt()
open(self.runner.app_last_exit_code, mode='w').write('0') open(self.runner.app_last_exit_code, mode='w').write('0')
@ -1969,7 +1986,7 @@ class MainWindow(QMainWindow):
self.hide() self.hide()
def window_toggle(self): def window_toggle(self):
self.window_hide() if self.isVisible() else self.window_show() self.window_show()
def window_position_reset(self): def window_position_reset(self):
self.setGeometry(self.window_x, self.window_y + (self.frameGeometry().height() - self.geometry().height()), self.window_w, self.window_h) self.setGeometry(self.window_x, self.window_y + (self.frameGeometry().height() - self.geometry().height()), self.window_w, self.window_h)
@ -2322,12 +2339,9 @@ class MainRunner:
web_listen_host=self.web_server_host, web_listen_host=self.web_server_host,
web_listen_port=self.web_server_port web_listen_port=self.web_server_port
) )
app_exec = '' status = self.application.exec_()
try: print('Exit status code: %s' % (status,), file=sys.stderr)
app_exec = self.application.exec_() sys.exit(status)
except Exception as e:
print(e, file=sys.stderr)
sys.exit(app_exec)
def build(self): def build(self):
if (str(__file__).endswith('.py')) == 0: if (str(__file__).endswith('.py')) == 0:
@ -2350,7 +2364,7 @@ class MainRunner:
'--include-module=fastapi', '--include-module=fastapi',
'--include-module=pydantic', '--include-module=pydantic',
'--include-module=starlette', '--include-module=starlette',
'--windows-console-mode=hide', '--windows-console-mode=disable',
'--windows-icon-from-ico=favicon.ico', '--windows-icon-from-ico=favicon.ico',
'--product-name=%s' % (self.app_name,), '--product-name=%s' % (self.app_name,),
'--file-description=%s' % (self.app_name,), '--file-description=%s' % (self.app_name,),
@ -2367,7 +2381,7 @@ class MainRunner:
ask = input('%s %s: ' % ('Compile setup program?', '[Y/n]')) ask = input('%s %s: ' % ('Compile setup program?', '[Y/n]'))
if ask.lower().strip() == 'y': if ask.lower().strip() == 'y':
compile_file = os.path.join(os.path.dirname(__file__), '%s.iss' % (os.path.splitext(os.path.basename(__file__))[0],)) compile_file = os.path.join(os.path.dirname(__file__), '%s.iss' % (os.path.splitext(os.path.basename(__file__))[0],))
compile_template = os.path.join(os.path.dirname(__file__), 'Compile.iss.template') compile_template = os.path.join(os.path.dirname(__file__), '%s.iss.template' % (os.path.splitext(os.path.basename(__file__))[0],))
compiler = 'C:\\Program Files (x86)\\Inno Setup 6\\ISCC.exe' compiler = 'C:\\Program Files (x86)\\Inno Setup 6\\ISCC.exe'
if (os.path.exists(compile_template)) != 1: if (os.path.exists(compile_template)) != 1:
print('The template file \"%s\" does not exist.' % (compile_template,), file=sys.stderr) print('The template file \"%s\" does not exist.' % (compile_template,), file=sys.stderr)