From 3a3aaf7bca71967d6e1e72b25ed79d26c07d1600 Mon Sep 17 00:00:00 2001 From: Navin Chandra Date: Fri, 14 Nov 2025 16:53:52 +0530 Subject: [PATCH 1/3] add emulation command `set_user_agent_override` --- .../webdriver/common/bidi/emulation.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/py/selenium/webdriver/common/bidi/emulation.py b/py/selenium/webdriver/common/bidi/emulation.py index b58d2ddbe0666..a8424b52a0821 100644 --- a/py/selenium/webdriver/common/bidi/emulation.py +++ b/py/selenium/webdriver/common/bidi/emulation.py @@ -399,3 +399,35 @@ def set_screen_orientation_override( params["userContexts"] = user_contexts self.conn.execute(command_builder("emulation.setScreenOrientationOverride", params)) + + def set_user_agent_override( + self, + user_agent: Optional[str] = None, + contexts: Optional[list[str]] = None, + user_contexts: Optional[list[str]] = None, + ) -> None: + """Set user agent override for the given contexts or user contexts. + + Args: + user_agent: User agent string to emulate, or None to clear the override. + contexts: List of browsing context IDs to apply the override to. + user_contexts: List of user context IDs to apply the override to. + + Raises: + ValueError: If both contexts and user_contexts are provided, or if neither + contexts nor user_contexts are provided. + """ + if contexts is not None and user_contexts is not None: + raise ValueError("Cannot specify both contexts and userContexts") + + if contexts is None and user_contexts is None: + raise ValueError("Must specify either contexts or userContexts") + + params: dict[str, Any] = {"userAgent": user_agent} + + if contexts is not None: + params["contexts"] = contexts + elif user_contexts is not None: + params["userContexts"] = user_contexts + + self.conn.execute(command_builder("emulation.setUserAgentOverride", params)) From fcc1b8332068290427af6dcd9874a3017d0a6a70 Mon Sep 17 00:00:00 2001 From: Navin Chandra Date: Fri, 14 Nov 2025 16:54:07 +0530 Subject: [PATCH 2/3] add tests --- .../webdriver/common/bidi_emulation_tests.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/py/test/selenium/webdriver/common/bidi_emulation_tests.py b/py/test/selenium/webdriver/common/bidi_emulation_tests.py index bcddb9e1320ac..60a56cdf6dbc1 100644 --- a/py/test/selenium/webdriver/common/bidi_emulation_tests.py +++ b/py/test/selenium/webdriver/common/bidi_emulation_tests.py @@ -98,6 +98,15 @@ def get_screen_orientation(driver, context_id): return {"type": orientation_type, "angle": orientation_angle} +def get_browser_user_agent(driver): + result = driver.script._evaluate( + "navigator.userAgent", + {"context": driver.current_window_handle}, + await_promise=False, + ) + return result.result["value"] + + def test_emulation_initialized(driver): assert driver.emulation is not None assert isinstance(driver.emulation, Emulation) @@ -527,3 +536,41 @@ def test_set_screen_orientation_override_with_user_contexts(driver, pages, natur driver.browsing_context.close(context_id) finally: driver.browser.remove_user_context(user_context) + + +def test_set_user_agent_override_with_contexts(driver, pages): + context_id = driver.current_window_handle + url = pages.url("formPage.html") + driver.browsing_context.navigate(context_id, url, wait="complete") + initial_user_agent = get_browser_user_agent(driver) + + custom_user_agent = "Mozilla/5.0 (Custom Test Agent)" + driver.emulation.set_user_agent_override(user_agent=custom_user_agent, contexts=[context_id]) + + assert get_browser_user_agent(driver) == custom_user_agent + + driver.emulation.set_user_agent_override(user_agent=None, contexts=[context_id]) + assert get_browser_user_agent(driver) == initial_user_agent + + +def test_set_user_agent_override_with_user_contexts(driver, pages): + user_context = driver.browser.create_user_context() + try: + context_id = driver.browsing_context.create(type=WindowTypes.TAB, user_context=user_context) + try: + driver.switch_to.window(context_id) + url = pages.url("formPage.html") + driver.browsing_context.navigate(context_id, url, wait="complete") + initial_user_agent = get_browser_user_agent(driver) + + custom_user_agent = "Mozilla/5.0 (Custom User Context Agent)" + driver.emulation.set_user_agent_override(user_agent=custom_user_agent, user_contexts=[user_context]) + + assert get_browser_user_agent(driver) == custom_user_agent + + driver.emulation.set_user_agent_override(user_agent=None, user_contexts=[user_context]) + assert get_browser_user_agent(driver) == initial_user_agent + finally: + driver.browsing_context.close(context_id) + finally: + driver.browser.remove_user_context(user_context) From 2c6c9823eca2604a82f5050cb15b062f6a1b93b7 Mon Sep 17 00:00:00 2001 From: Navin Chandra Date: Fri, 14 Nov 2025 21:46:42 +0530 Subject: [PATCH 3/3] address review comments --- py/selenium/webdriver/common/bidi/emulation.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/py/selenium/webdriver/common/bidi/emulation.py b/py/selenium/webdriver/common/bidi/emulation.py index a8424b52a0821..85558d4b0f4f3 100644 --- a/py/selenium/webdriver/common/bidi/emulation.py +++ b/py/selenium/webdriver/common/bidi/emulation.py @@ -402,9 +402,9 @@ def set_screen_orientation_override( def set_user_agent_override( self, - user_agent: Optional[str] = None, - contexts: Optional[list[str]] = None, - user_contexts: Optional[list[str]] = None, + user_agent: str | None = None, + contexts: list[str] | None = None, + user_contexts: list[str] | None = None, ) -> None: """Set user agent override for the given contexts or user contexts. @@ -418,10 +418,10 @@ def set_user_agent_override( contexts nor user_contexts are provided. """ if contexts is not None and user_contexts is not None: - raise ValueError("Cannot specify both contexts and userContexts") + raise ValueError("Cannot specify both contexts and user_contexts") if contexts is None and user_contexts is None: - raise ValueError("Must specify either contexts or userContexts") + raise ValueError("Must specify either contexts or user_contexts") params: dict[str, Any] = {"userAgent": user_agent}