Skip to content

Commit 6879071

Browse files
authored
Merge branch 'trunk' into rb_add_guard_for_beta_firefox
2 parents b2baba9 + 2bf42e9 commit 6879071

File tree

16 files changed

+103
-120
lines changed

16 files changed

+103
-120
lines changed

common/repositories.bzl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ js_library(
5050

5151
http_archive(
5252
name = "linux_beta_firefox",
53-
url = "https://ftp.mozilla.org/pub/firefox/releases/142.0b8/linux-x86_64/en-US/firefox-142.0b8.tar.xz",
54-
sha256 = "52c7c24dcc1258c9cd43c7b070def0a93bae58d2f5d077d11a7979307857e5c2",
53+
url = "https://ftp.mozilla.org/pub/firefox/releases/142.0b9/linux-x86_64/en-US/firefox-142.0b9.tar.xz",
54+
sha256 = "0e230f54a1d933df55e0d730c7d774437e60b5fdcbd74401f5da69bce184c30b",
5555
build_file_content = """
5656
load("@aspect_rules_js//js:defs.bzl", "js_library")
5757
package(default_visibility = ["//visibility:public"])
@@ -72,8 +72,8 @@ js_library(
7272

7373
dmg_archive(
7474
name = "mac_beta_firefox",
75-
url = "https://ftp.mozilla.org/pub/firefox/releases/142.0b8/mac/en-US/Firefox%20142.0b8.dmg",
76-
sha256 = "74c20a61fcc05fd69427f370a6a97ab660615299ef254d4cfaa617ec095dba98",
75+
url = "https://ftp.mozilla.org/pub/firefox/releases/142.0b9/mac/en-US/Firefox%20142.0b9.dmg",
76+
sha256 = "529509a53278d8cbd482fa8ef95ac243b33c6cc4acc7924c15f6ce3f59c64bbf",
7777
build_file_content = """
7878
load("@aspect_rules_js//js:defs.bzl", "js_library")
7979
package(default_visibility = ["//visibility:public"])
@@ -165,8 +165,8 @@ js_library(
165165

166166
http_archive(
167167
name = "linux_edgedriver",
168-
url = "https://msedgedriver.microsoft.com/138.0.3351.121/edgedriver_linux64.zip",
169-
sha256 = "1a0bed812b1b84f1093fa1e759cae2a210481620cd9ea3cb91dc2a60e0b21e4d",
168+
url = "https://msedgedriver.microsoft.com/139.0.3405.86/edgedriver_linux64.zip",
169+
sha256 = "49ce29de50f9ac418a3a2416708a5563215b8412b27d3e505f3c859fc6ffba12",
170170
build_file_content = """
171171
load("@aspect_rules_js//js:defs.bzl", "js_library")
172172
package(default_visibility = ["//visibility:public"])
@@ -182,8 +182,8 @@ js_library(
182182

183183
http_archive(
184184
name = "mac_edgedriver",
185-
url = "https://msedgedriver.microsoft.com/138.0.3351.121/edgedriver_mac64.zip",
186-
sha256 = "96b648865de254ae5db7008676340b16476e39b0b90c2da71964c14cb53a0195",
185+
url = "https://msedgedriver.microsoft.com/139.0.3405.86/edgedriver_mac64.zip",
186+
sha256 = "b6c8244dfb7b8a223d3ac8fd569533f0a307eadaca2b8cbc884ce7f69294682e",
187187
build_file_content = """
188188
load("@aspect_rules_js//js:defs.bzl", "js_library")
189189
package(default_visibility = ["//visibility:public"])

py/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ py_wheel(
327327
python_requires = ">=3.9",
328328
python_tag = "py3",
329329
requires = [
330-
"urllib3[socks]~=2.5.0",
330+
"urllib3[socks]>=2.5.0,<3.0",
331331
"trio~=0.30.0",
332332
"trio-websocket~=0.12.2",
333333
"certifi>=2025.6.15",

py/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ classifiers = [
2626
"Programming Language :: Python :: 3.13",
2727
]
2828
dependencies = [
29-
"urllib3[socks]~=2.5.0",
29+
"urllib3[socks]>=2.5.0,<3.0",
3030
"trio~=0.30.0",
3131
"trio-websocket~=0.12.2",
3232
"certifi>=2025.6.15",

py/selenium/webdriver/common/bidi/session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
from typing import Dict, Optional
18+
from typing import Optional
1919

2020
from selenium.webdriver.common.bidi.common import command_builder
2121

@@ -77,7 +77,7 @@ def __init__(
7777
self.file = file
7878
self.prompt = prompt
7979

80-
def to_dict(self) -> Dict[str, str]:
80+
def to_dict(self) -> dict[str, str]:
8181
"""Convert the UserPromptHandler to a dictionary for BiDi protocol.
8282
8383
Returns:

py/selenium/webdriver/remote/remote_connection.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from base64 import b64encode
2323
from typing import Optional
2424
from urllib import parse
25-
from urllib.parse import urlparse
25+
from urllib.parse import unquote, urlparse
2626

2727
import urllib3
2828

@@ -298,7 +298,9 @@ def _get_connection_manager(self):
298298
return SOCKSProxyManager(self._proxy_url, **pool_manager_init_args)
299299
if self._identify_http_proxy_auth():
300300
self._proxy_url, self._basic_proxy_auth = self._separate_http_proxy_auth()
301-
pool_manager_init_args["proxy_headers"] = urllib3.make_headers(proxy_basic_auth=self._basic_proxy_auth)
301+
pool_manager_init_args["proxy_headers"] = urllib3.make_headers(
302+
proxy_basic_auth=unquote(self._basic_proxy_auth)
303+
)
302304
return urllib3.ProxyManager(self._proxy_url, **pool_manager_init_args)
303305

304306
return urllib3.PoolManager(**pool_manager_init_args)

py/selenium/webdriver/remote/webdriver.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,10 @@ def start_devtools(self):
12111211
raise RuntimeError("CDP support for Firefox has been removed. Please switch to WebDriver BiDi.")
12121212
self._websocket_connection = WebSocketConnection(ws_url)
12131213
targets = self._websocket_connection.execute(self._devtools.target.get_targets())
1214-
target_id = targets[0].target_id
1214+
for target in targets:
1215+
if target.target_id == self.current_window_handle:
1216+
target_id = target.target_id
1217+
break
12151218
session = self._websocket_connection.execute(self._devtools.target.attach_to_target(target_id, True))
12161219
self._websocket_connection.session_id = session
12171220
return self._devtools, self._websocket_connection
@@ -1232,7 +1235,10 @@ async def bidi_connection(self):
12321235
devtools = cdp.import_devtools(version)
12331236
async with cdp.open_cdp(ws_url) as conn:
12341237
targets = await conn.execute(devtools.target.get_targets())
1235-
target_id = targets[0].target_id
1238+
for target in targets:
1239+
if target.target_id == self.current_window_handle:
1240+
target_id = target.target_id
1241+
break
12361242
async with conn.open_session(target_id) as session:
12371243
yield BidiConnection(session, cdp, devtools)
12381244

@@ -1423,7 +1429,7 @@ def _get_cdp_details(self):
14231429
try:
14241430
if self.caps.get("browserName") == "chrome":
14251431
debugger_address = self.caps.get("goog:chromeOptions").get("debuggerAddress")
1426-
elif self.caps.get("browserName") == "MicrosoftEdge":
1432+
elif self.caps.get("browserName") in ("MicrosoftEdge", "webview2"):
14271433
debugger_address = self.caps.get("ms:edgeOptions").get("debuggerAddress")
14281434
except AttributeError:
14291435
raise WebDriverException("Can't get debugger address.")

py/test/unit/selenium/webdriver/remote/remote_connection_tests.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18+
import base64
1819
import os
1920
from unittest.mock import patch
2021
from urllib import parse
@@ -544,3 +545,58 @@ def test_connection_manager_with_custom_args_via_client_config():
544545
assert isinstance(conn, PoolManager)
545546
assert conn.connection_pool_kw["retries"] == retries
546547
assert conn.connection_pool_kw["timeout"] == timeout
548+
549+
550+
def test_proxy_auth_with_special_characters_url_encoded():
551+
proxy_url = "http://user:passw%[email protected]:8080"
552+
client_config = ClientConfig(
553+
remote_server_addr="http://localhost:4444",
554+
keep_alive=False,
555+
proxy=Proxy({"proxyType": ProxyType.MANUAL, "httpProxy": proxy_url}),
556+
)
557+
remote_connection = RemoteConnection(client_config=client_config)
558+
559+
proxy_without_auth, basic_auth = remote_connection._separate_http_proxy_auth()
560+
561+
assert proxy_without_auth == "http://proxy.example.com:8080"
562+
assert basic_auth == "user:passw%23rd" # Still URL-encoded
563+
564+
conn = remote_connection._get_connection_manager()
565+
assert isinstance(conn, ProxyManager)
566+
567+
expected_auth = base64.b64encode("user:passw#rd".encode()).decode() # Decoded password
568+
expected_headers = make_headers(proxy_basic_auth="user:passw#rd") # Unquoted password
569+
570+
assert conn.proxy_headers == expected_headers
571+
assert conn.proxy_headers["proxy-authorization"] == f"Basic {expected_auth}"
572+
573+
574+
def test_proxy_auth_with_multiple_special_characters():
575+
test_cases = [
576+
("passw%23rd", "passw#rd"), # # character
577+
("passw%40rd", "passw@rd"), # @ character
578+
("passw%26rd", "passw&rd"), # & character
579+
("passw%3Drd", "passw=rd"), # = character
580+
("passw%2Brd", "passw+rd"), # + character
581+
("passw%20rd", "passw rd"), # space character
582+
("passw%21%40%23%24", "passw!@#$"), # Multiple special chars
583+
]
584+
585+
for encoded_password, decoded_password in test_cases:
586+
proxy_url = f"http://testuser:{encoded_password}@proxy.example.com:8080"
587+
client_config = ClientConfig(
588+
remote_server_addr="http://localhost:4444",
589+
keep_alive=False,
590+
proxy=Proxy({"proxyType": ProxyType.MANUAL, "httpProxy": proxy_url}),
591+
)
592+
remote_connection = RemoteConnection(client_config=client_config)
593+
594+
proxy_without_auth, basic_auth = remote_connection._separate_http_proxy_auth()
595+
assert basic_auth == f"testuser:{encoded_password}"
596+
597+
conn = remote_connection._get_connection_manager()
598+
expected_auth = base64.b64encode(f"testuser:{decoded_password}".encode()).decode()
599+
expected_headers = make_headers(proxy_basic_auth=f"testuser:{decoded_password}")
600+
601+
assert conn.proxy_headers == expected_headers
602+
assert conn.proxy_headers["proxy-authorization"] == f"Basic {expected_auth}"

rb/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ PATH
77
base64 (~> 0.2)
88
logger (~> 1.4)
99
rexml (~> 3.2, >= 3.2.5)
10-
rubyzip (>= 1.2.2, < 3.0)
10+
rubyzip (>= 1.2.2, < 4.0)
1111
websocket (~> 1.0)
1212

1313
GEM
@@ -147,7 +147,7 @@ GEM
147147
lint_roller (~> 1.1)
148148
rubocop (~> 1.72, >= 1.72.1)
149149
ruby-progressbar (1.13.0)
150-
rubyzip (2.4.1)
150+
rubyzip (3.0.0)
151151
securerandom (0.4.1)
152152
steep (1.5.3)
153153
activesupport (>= 5.1)

rb/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@ def download_file(file_name, target_directory)
3939

4040
begin
4141
Zip::File.open("#{file_name}.zip") do |zip|
42-
zip.each { |entry| zip.extract(entry, "#{target_directory}#{file_name}") }
42+
zip.each do |entry|
43+
if Zipper::RUBYZIP_V3
44+
zip.extract(entry, file_name, destination_directory: target_directory)
45+
else
46+
zip.extract(entry, "#{target_directory}#{file_name}")
47+
end
48+
end
4349
end
4450
ensure
4551
FileUtils.rm_f("#{file_name}.zip")

rb/lib/selenium/webdriver/common/zipper.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
# under the License.
1919

2020
require 'zip'
21+
require 'zip/version' # Not required automatically
2122
require 'tempfile'
2223
require 'find'
2324
require 'base64'
@@ -30,6 +31,7 @@ module WebDriver
3031

3132
module Zipper
3233
EXTENSIONS = %w[.zip .xpi].freeze
34+
RUBYZIP_V3 = Zip::VERSION >= '3.0.0'
3335

3436
class << self
3537
def unzip(path)
@@ -42,7 +44,11 @@ def unzip(path)
4244
dirname = File.dirname(to)
4345

4446
FileUtils.mkdir_p dirname
45-
zip.extract(entry, to)
47+
if RUBYZIP_V3
48+
zip.extract(entry, entry.name, destination_directory: destination)
49+
else
50+
zip.extract(entry, to)
51+
end
4652
end
4753
end
4854

@@ -75,7 +81,11 @@ def with_tmp_zip(&blk)
7581
# Don't use Tempfile since it lacks rb_file_s_rename permission on Windows.
7682
Dir.mktmpdir do |tmp_dir|
7783
zip_path = File.join(tmp_dir, 'webdriver-zip')
78-
Zip::File.open(zip_path, Zip::File::CREATE, &blk)
84+
if RUBYZIP_V3
85+
Zip::File.open(zip_path, create: true, &blk)
86+
else
87+
Zip::File.open(zip_path, Zip::File::CREATE, &blk)
88+
end
7989
end
8090
end
8191

0 commit comments

Comments
 (0)