Function optimization, use new browser window activation solution

This commit is contained in:
zhaoyafan 2025-03-02 18:55:28 +08:00
parent ed496a08c2
commit 45e6a627bb
3 changed files with 117 additions and 20 deletions

View File

@ -18,6 +18,9 @@ import hashlib
import asyncio import asyncio
import tempfile import tempfile
import platform import platform
import win32gui
import win32process
import win32con
import requests import requests
import requests.adapters import requests.adapters
import importlib.util import importlib.util
@ -771,6 +774,51 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
except Exception: except Exception:
return '' return ''
@property
def window_titles(self):
"""
Return to title list.
"""
result = []
try:
targets = self.execute_cdp_cmd('Target.getTargets', {})
for target in targets['targetInfos']:
if (target['type'] == 'page') == 1:
result.append(target['title'])
except Exception:
pass
return result[::-1]
@property
def window_urls(self):
"""
Return to url list.
"""
result = []
try:
targets = self.execute_cdp_cmd('Target.getTargets', {})
for target in targets['targetInfos']:
if (target['type'] == 'page') == 1:
result.append(target['url'])
except Exception:
pass
return result[::-1]
@property
def window_handles(self):
"""
Return to window handle list.
"""
result = []
try:
targets = self.execute_cdp_cmd('Target.getTargets', {})
for target in targets['targetInfos']:
if (target['type'] == 'page') == 1:
result.append(target['targetId'])
except Exception:
pass
return result[::-1]
@property @property
def window_inner_size(self) -> tuple: def window_inner_size(self) -> tuple:
""" """
@ -842,7 +890,6 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
except Exception: except Exception:
pass pass
@calculate_execution_time
def quit_backend(self): def quit_backend(self):
""" """
Exit the browser backend. Exit the browser backend.
@ -1004,6 +1051,14 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
self.switch_to.default_content() self.switch_to.default_content()
self.wait(0.2) self.wait(0.2)
def tab_active(self):
"""
Activate current tab.
"""
self.switch_to.window(self.current_window_handle)
self.wait(0.2)
self._update_cdp_command()
def tab_create(self, url: str = None): def tab_create(self, url: str = None):
""" """
Create a new tab and open the URL. Create a new tab and open the URL.
@ -1651,18 +1706,35 @@ class BrowserManager:
continue continue
running.update_status_running() running.update_status_running()
def _get_user_process_id(self, user_id: str):
try:
return int(self.data_storage['browser_user'][user_id]['process_id'])
except KeyError:
return None
def _get_user_name(self, user_id: str): def _get_user_name(self, user_id: str):
return str(self.data_storage['browser_user'][user_id]['user_name'] or '') try:
return str(self.data_storage['browser_user'][user_id]['user_name'])
except KeyError:
return None
def _get_user_data_dir(self, user_id: str): def _get_user_data_dir(self, user_id: str):
try:
return os.path.join(self.browser_data_home, self.data_storage['browser_user'][user_id]['user_data_dir']) return os.path.join(self.browser_data_home, self.data_storage['browser_user'][user_id]['user_data_dir'])
except KeyError:
return None
def _get_user_remote_debugging_port(self, user_id: str): def _get_user_remote_debugging_port(self, user_id: str):
try:
return int(self.data_storage['browser_user'][user_id]['remote_debugging_port']) return int(self.data_storage['browser_user'][user_id]['remote_debugging_port'])
except KeyError:
return None
def _get_user_app_id(self, user_id: str): def _get_user_app_id(self, user_id: str):
user_name = self.data_storage['browser_user'][user_id]['user_name'] try:
return user_name or user_id return self.data_storage['browser_user'][user_id]['user_name'] or user_id
except KeyError:
return user_id
def _initialize_user_running(self, user_id: str): def _initialize_user_running(self, user_id: str):
return BrowserManagerUserRunning( return BrowserManagerUserRunning(
@ -1698,6 +1770,23 @@ class BrowserManager:
except Exception as e: except Exception as e:
print(e, file=sys.stderr) print(e, file=sys.stderr)
@staticmethod
def get_chrome_hwnd(pid: int):
if pid:
def callback(hwnd, hwnds):
if win32gui.IsWindowVisible(hwnd) and win32gui.GetParent(hwnd) == 0:
_, found_pid = win32process.GetWindowThreadProcessId(hwnd)
if found_pid == pid and 'Chrome_' in win32gui.GetClassName(hwnd):
ws = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
if (ws & win32con.WS_EX_TOOLWINDOW) == 0 and (ws & win32con.WS_EX_PALETTEWINDOW) == 0:
hwnds.append(hwnd)
return False
hwnds = []
win32gui.EnumWindows(callback, hwnds)
return hwnds[0] if hwnds else None
else:
return None
def run_browser(self, user_data_dir: str, remote_debugging_port: int, proxy_server: str = None): def run_browser(self, user_data_dir: str, remote_debugging_port: int, proxy_server: str = None):
options = [ options = [
self.binary, self.binary,
@ -1714,7 +1803,7 @@ class BrowserManager:
options.append('--remote-debugging-port=%s' % (remote_debugging_port,)) options.append('--remote-debugging-port=%s' % (remote_debugging_port,))
if proxy_server: if proxy_server:
options.append('--proxy-server=%s' % (proxy_server,)) options.append('--proxy-server=%s' % (proxy_server,))
return subprocess.Popen(options, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True) return subprocess.Popen(options, shell=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, start_new_session=True)
@staticmethod @staticmethod
def clear_dirs(dirs): def clear_dirs(dirs):
@ -1933,7 +2022,6 @@ class BrowserManager:
self.user_operate_complete(user_id) self.user_operate_complete(user_id)
raise raise
@func_set_timeout(0.55)
@calculate_execution_time @calculate_execution_time
def user_focus_window(self, user_id: str): def user_focus_window(self, user_id: str):
if (user_id in self.user_ids()) == 0: if (user_id in self.user_ids()) == 0:
@ -1941,12 +2029,20 @@ class BrowserManager:
if (user_id in self.user_ids_online()) == 0: if (user_id in self.user_ids_online()) == 0:
raise FileExistsError('User ID is not running.') raise FileExistsError('User ID is not running.')
try: try:
self.user_running[user_id].driver.minimize_window() chrome_hwnd = self.get_chrome_hwnd(self._get_user_process_id(user_id))
self.user_running[user_id].driver.set_window_rect( if chrome_hwnd:
for _ in range(1 + int(bool(win32gui.IsIconic(chrome_hwnd)))):
win32gui.ShowWindow(chrome_hwnd, win32con.SW_RESTORE)
win32gui.ShowWindow(chrome_hwnd, win32con.SW_RESTORE)
win32gui.SetForegroundWindow(chrome_hwnd)
win32gui.SetWindowPos(
chrome_hwnd,
win32con.HWND_NOTOPMOST,
self.geometry_config['browser_window_x'], self.geometry_config['browser_window_x'],
self.geometry_config['browser_window_y'], self.geometry_config['browser_window_y'],
self.geometry_config['browser_window_w'], self.geometry_config['browser_window_w'],
self.geometry_config['browser_window_h'] self.geometry_config['browser_window_h'],
win32con.SWP_NOZORDER
) )
except Exception: except Exception:
pass pass
@ -2013,7 +2109,10 @@ class BrowserManager:
running = BrowserManagerUserRunning(self.user_running[user_id]) running = BrowserManagerUserRunning(self.user_running[user_id])
running.active = 1 running.active = 1
if (self.is_user_data_occupied(user_id)) == 0: if (self.is_user_data_occupied(user_id)) == 0:
self.run_browser(user_data_dir=user_data_dir, remote_debugging_port=remote_debugging_port, proxy_server='127.0.0.1:%s' % (mitmproxy_port,) if self.use_selenium_wire else None) browser_process = self.run_browser(user_data_dir=user_data_dir, remote_debugging_port=remote_debugging_port, proxy_server='127.0.0.1:%s' % (mitmproxy_port,) if self.use_selenium_wire else None)
self.data_storage['browser_user'][user_id]['process_id'] = browser_process.pid
self.data_storage.save()
print('The browser starts, and the process ID is %s.' % (browser_process.pid,), file=sys.stderr)
driver = Browser( driver = Browser(
driver=self.driver, driver=self.driver,
binary=self.binary, binary=self.binary,
@ -2446,8 +2545,6 @@ class WebServer:
try: try:
self.browser_manager.user_focus_window(data.data['user_id']) self.browser_manager.user_focus_window(data.data['user_id'])
return self.message(0) return self.message(0)
except FunctionTimedOut:
return self.message(0)
except Exception as e: except Exception as e:
return self.message(1, '%s' % (e,)) return self.message(1, '%s' % (e,))
@ -2536,7 +2633,7 @@ class MainRunner:
self.app_data = os.path.join(appdata, 'Galactic') if appdata else os.path.join(os.path.dirname(__file__), 'data') self.app_data = os.path.join(appdata, 'Galactic') if appdata else os.path.join(os.path.dirname(__file__), 'data')
self.app_running_file = os.path.join(self.app_data, 'running') self.app_running_file = os.path.join(self.app_data, 'running')
self.app_name = 'Galactic' self.app_name = 'Galactic'
self.app_version = '1.0.0.3' self.app_version = '1.0.0.4'
self.web_server_host = '127.0.0.1' self.web_server_host = '127.0.0.1'
self.web_server_port = 8095 self.web_server_port = 8095
self.web_server = None self.web_server = None

Binary file not shown.

File diff suppressed because one or more lines are too long