diff --git a/requirements.txt b/requirements.txt index a85f6e42ec9..9cddf0cc5c3 100755 --- a/requirements.txt +++ b/requirements.txt @@ -64,7 +64,7 @@ pygments==2.17.2;python_version<"3.8" pygments==2.18.0;python_version>="3.8" pyreadline3==3.4.1;platform_system=="Windows" tabcompleter==1.3.0 -pdbp==1.5.0 +pdbp==1.5.1 colorama==0.4.6 pyotp==2.9.0 python-xlib==0.33;platform_system=="Linux" diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py index 0f4cb9997d3..1411c85c750 100755 --- a/seleniumbase/__version__.py +++ b/seleniumbase/__version__.py @@ -1,2 +1,2 @@ # seleniumbase package -__version__ = "4.28.1" +__version__ = "4.28.2" diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py index 0d21607aced..0cfde0b2a07 100644 --- a/seleniumbase/core/browser_launcher.py +++ b/seleniumbase/core/browser_launcher.py @@ -389,7 +389,9 @@ def uc_special_open_if_cf( driver.execute_script('window.open("%s","_blank");' % url) driver.close() if mobile_emulator: - driver.switch_to.window(driver.window_handles[-1]) + page_actions.switch_to_window( + driver, driver.window_handles[-1], 2 + ) uc_metrics = {} if ( isinstance(device_width, int) @@ -419,7 +421,9 @@ def uc_special_open_if_cf( except Exception: pass if not mobile_emulator: - driver.switch_to.window(driver.window_handles[-1]) + page_actions.switch_to_window( + driver, driver.window_handles[-1], 2 + ) else: driver.default_get(url) # The original one else: @@ -450,7 +454,7 @@ def uc_open_with_tab(driver, url): with driver: driver.execute_script('window.open("%s","_blank");' % url) driver.close() - driver.switch_to.window(driver.window_handles[-1]) + page_actions.switch_to_window(driver, driver.window_handles[-1], 2) else: driver.default_get(url) # The original one return None @@ -476,10 +480,14 @@ def uc_open_with_reconnect(driver, url, reconnect_time=None): driver.reconnect(reconnect_time) time.sleep(0.004) try: - driver.switch_to.window(driver.window_handles[-1]) + page_actions.switch_to_window( + driver, driver.window_handles[-1], 2 + ) except InvalidSessionIdException: time.sleep(0.05) - driver.switch_to.window(driver.window_handles[-1]) + page_actions.switch_to_window( + driver, driver.window_handles[-1], 2 + ) else: driver.default_get(url) # The original one return None @@ -546,17 +554,17 @@ def uc_click( driver.reconnect(reconnect_time) -def verify_pyautogui_has_a_headed_browser(): +def verify_pyautogui_has_a_headed_browser(driver): """PyAutoGUI requires a headed browser so that it can focus on the correct element when performing actions.""" - if sb_config.headless or sb_config.headless2: + if hasattr(driver, "_is_hidden") and driver._is_hidden: raise Exception( "PyAutoGUI can't be used in headless mode!" ) -def install_pyautogui_if_missing(): - verify_pyautogui_has_a_headed_browser() +def install_pyautogui_if_missing(driver): + verify_pyautogui_has_a_headed_browser(driver) pip_find_lock = fasteners.InterProcessLock( constants.PipInstall.FINDLOCK ) @@ -608,7 +616,7 @@ def get_configured_pyautogui(pyautogui_copy): def uc_gui_press_key(driver, key): - install_pyautogui_if_missing() + install_pyautogui_if_missing(driver) import pyautogui pyautogui = get_configured_pyautogui(pyautogui) gui_lock = fasteners.InterProcessLock( @@ -619,7 +627,7 @@ def uc_gui_press_key(driver, key): def uc_gui_press_keys(driver, keys): - install_pyautogui_if_missing() + install_pyautogui_if_missing(driver) import pyautogui pyautogui = get_configured_pyautogui(pyautogui) gui_lock = fasteners.InterProcessLock( @@ -631,7 +639,7 @@ def uc_gui_press_keys(driver, keys): def uc_gui_write(driver, text): - install_pyautogui_if_missing() + install_pyautogui_if_missing(driver) import pyautogui pyautogui = get_configured_pyautogui(pyautogui) gui_lock = fasteners.InterProcessLock( @@ -648,7 +656,7 @@ def uc_gui_handle_cf(driver, frame="iframe"): and 'aria-label="Cloudflare"' not in source ): return - install_pyautogui_if_missing() + install_pyautogui_if_missing(driver) import pyautogui pyautogui = get_configured_pyautogui(pyautogui) gui_lock = fasteners.InterProcessLock( @@ -664,9 +672,7 @@ def uc_gui_handle_cf(driver, frame="iframe"): if not is_in_frame: # Make sure the window is on top page_actions.switch_to_window( - driver, - driver.current_window_handle, - timeout=settings.SMALL_TIMEOUT, + driver, driver.current_window_handle, 2 ) if not is_in_frame or needs_switch: # Currently not in frame (or nested frame outside CF one) @@ -1634,10 +1640,6 @@ def get_driver( if headless2 and browser_name == constants.Browser.FIREFOX: headless2 = False # Only for Chromium headless = True - if not hasattr(sb_config, "headless"): - sb_config.headless = headless - if not hasattr(sb_config, "headless2"): - sb_config.headless2 = headless2 if ( binary_location and isinstance(binary_location, str) @@ -4035,6 +4037,8 @@ def get_local_driver( driver, *args, **kwargs ) ) + driver._is_hidden = (headless or headless2) + driver._is_using_uc = True if mobile_emulator: uc_metrics = {} if ( diff --git a/seleniumbase/fixtures/page_actions.py b/seleniumbase/fixtures/page_actions.py index 9564763388c..6ca81912282 100644 --- a/seleniumbase/fixtures/page_actions.py +++ b/seleniumbase/fixtures/page_actions.py @@ -18,6 +18,7 @@ By.PARTIAL_LINK_TEXT # "partial link text" """ import codecs +import fasteners import os import time from selenium.common.exceptions import ElementNotInteractableException @@ -32,6 +33,7 @@ from seleniumbase.common.exceptions import LinkTextNotFoundException from seleniumbase.common.exceptions import TextNotVisibleException from seleniumbase.config import settings +from seleniumbase.fixtures import constants from seleniumbase.fixtures import page_utils from seleniumbase.fixtures import shared_utils @@ -1428,6 +1430,18 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT): timeout_exception(Exception, message) +def __switch_to_window(driver, window_handle): + if hasattr(driver, "_is_using_uc") and driver._is_using_uc: + gui_lock = fasteners.InterProcessLock( + constants.MultiBrowser.PYAUTOGUILOCK + ) + with gui_lock: + driver.switch_to.window(window_handle) + else: + driver.switch_to.window(window_handle) + return True + + def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT): """ Wait for a window to appear, and switch to it. This should be usable @@ -1451,7 +1465,7 @@ def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT): shared_utils.check_if_time_limit_exceeded() try: window_handle = driver.window_handles[window] - driver.switch_to.window(window_handle) + __switch_to_window(driver, window_handle) return True except IndexError: now_ms = time.time() * 1000.0 @@ -1472,7 +1486,7 @@ def switch_to_window(driver, window, timeout=settings.SMALL_TIMEOUT): for x in range(int(timeout * 10)): shared_utils.check_if_time_limit_exceeded() try: - driver.switch_to.window(window_handle) + __switch_to_window(driver, window_handle) return True except NoSuchWindowException: now_ms = time.time() * 1000.0 diff --git a/seleniumbase/undetected/__init__.py b/seleniumbase/undetected/__init__.py index be6f4fb0766..40283f43350 100644 --- a/seleniumbase/undetected/__init__.py +++ b/seleniumbase/undetected/__init__.py @@ -278,15 +278,19 @@ def __init__( options.binary_location, *options.arguments ) else: - browser = subprocess.Popen( - [options.binary_location, *options.arguments], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=IS_POSIX, - creationflags=creationflags, + gui_lock = fasteners.InterProcessLock( + constants.MultiBrowser.PYAUTOGUILOCK ) - self.browser_pid = browser.pid + with gui_lock: + browser = subprocess.Popen( + [options.binary_location, *options.arguments], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + close_fds=IS_POSIX, + creationflags=creationflags, + ) + self.browser_pid = browser.pid service_ = None log_output = subprocess.PIPE if sys.version_info < (3, 8): diff --git a/setup.py b/setup.py index 02cd9a60108..5f59c7b9976 100755 --- a/setup.py +++ b/setup.py @@ -212,7 +212,7 @@ 'pygments==2.18.0;python_version>="3.8"', 'pyreadline3==3.4.1;platform_system=="Windows"', "tabcompleter==1.3.0", - "pdbp==1.5.0", + "pdbp==1.5.1", 'colorama==0.4.6', 'pyotp==2.9.0', 'python-xlib==0.33;platform_system=="Linux"',