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 tempfile
import platform
import win32gui
import win32process
import win32con
import requests
import requests.adapters
import importlib.util
@ -771,6 +774,51 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
except Exception:
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
def window_inner_size(self) -> tuple:
"""
@ -842,7 +890,6 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
except Exception:
pass
@calculate_execution_time
def quit_backend(self):
"""
Exit the browser backend.
@ -1004,6 +1051,14 @@ class Browser(InspectRequestsMixin, DriverCommonMixin, Chrome):
self.switch_to.default_content()
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):
"""
Create a new tab and open the URL.
@ -1651,18 +1706,35 @@ class BrowserManager:
continue
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):
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):
return os.path.join(self.browser_data_home, self.data_storage['browser_user'][user_id]['user_data_dir'])
try:
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):
return int(self.data_storage['browser_user'][user_id]['remote_debugging_port'])
try:
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):
user_name = self.data_storage['browser_user'][user_id]['user_name']
return user_name or user_id
try:
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):
return BrowserManagerUserRunning(
@ -1698,6 +1770,23 @@ class BrowserManager:
except Exception as e:
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):
options = [
self.binary,
@ -1714,7 +1803,7 @@ class BrowserManager:
options.append('--remote-debugging-port=%s' % (remote_debugging_port,))
if 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
def clear_dirs(dirs):
@ -1933,7 +2022,6 @@ class BrowserManager:
self.user_operate_complete(user_id)
raise
@func_set_timeout(0.55)
@calculate_execution_time
def user_focus_window(self, user_id: str):
if (user_id in self.user_ids()) == 0:
@ -1941,13 +2029,21 @@ class BrowserManager:
if (user_id in self.user_ids_online()) == 0:
raise FileExistsError('User ID is not running.')
try:
self.user_running[user_id].driver.minimize_window()
self.user_running[user_id].driver.set_window_rect(
self.geometry_config['browser_window_x'],
self.geometry_config['browser_window_y'],
self.geometry_config['browser_window_w'],
self.geometry_config['browser_window_h']
)
chrome_hwnd = self.get_chrome_hwnd(self._get_user_process_id(user_id))
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_y'],
self.geometry_config['browser_window_w'],
self.geometry_config['browser_window_h'],
win32con.SWP_NOZORDER
)
except Exception:
pass
@ -2013,7 +2109,10 @@ class BrowserManager:
running = BrowserManagerUserRunning(self.user_running[user_id])
running.active = 1
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=self.driver,
binary=self.binary,
@ -2446,8 +2545,6 @@ class WebServer:
try:
self.browser_manager.user_focus_window(data.data['user_id'])
return self.message(0)
except FunctionTimedOut:
return self.message(0)
except Exception as 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_running_file = os.path.join(self.app_data, 'running')
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_port = 8095
self.web_server = None

Binary file not shown.

File diff suppressed because one or more lines are too long