refactor: reorganize client transport and extension internals
- Split client, native, remote, serve, markdown, and SDK internals into focused packages with direct imports. - Move local and remote transport framing/protocol helpers behind clearer module boundaries. - Break up the extension injected DOM logic into a separate content dispatch bundle and dedicated content modules. - Add explicit client handling for passive remote discovery without noisy PQ warnings. - Keep behavior covered with updated unit, integration, and extension tests.
This commit is contained in:
+47
-8
@@ -206,7 +206,7 @@ class TestAuthSuccess:
|
||||
key_path.write_bytes(pem)
|
||||
priv = load_private_key(key_path)
|
||||
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", _mock_no_browser)
|
||||
|
||||
client, server = _pair()
|
||||
t = threading.Thread(
|
||||
@@ -238,7 +238,7 @@ class TestAuthSuccess:
|
||||
key_path.write_bytes(pem)
|
||||
priv = load_private_key(key_path)
|
||||
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", _mock_no_browser)
|
||||
|
||||
client, server = _pair()
|
||||
t = _spawn(server, path)
|
||||
@@ -258,7 +258,7 @@ class TestAuthSuccess:
|
||||
|
||||
def test_post_quantum_kex_auth_reaches_proxy(self, tmp_path, monkeypatch):
|
||||
"""ML-KEM shared secret is decapsulated and bound to the auth signature."""
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.auth.pq_kex_server_keypair", lambda: ("fake-private", b"fake-public"))
|
||||
monkeypatch.setattr("browser_cli.auth.pq_kex_server_decapsulate", lambda priv, ct: b"pq-secret")
|
||||
|
||||
@@ -298,7 +298,7 @@ class TestAuthSuccess:
|
||||
|
||||
def test_post_quantum_encrypted_transport_reaches_proxy(self, tmp_path, monkeypatch):
|
||||
"""New clients encrypt the command payload and receive encrypted responses."""
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.auth.pq_kex_server_keypair", lambda: ("fake-private", b"fake-public"))
|
||||
monkeypatch.setattr("browser_cli.auth.pq_kex_server_decapsulate", lambda priv, ct: b"pq-secret")
|
||||
|
||||
@@ -347,7 +347,7 @@ class TestAuthSuccess:
|
||||
|
||||
def test_no_auth_mode_reaches_proxy(self, monkeypatch):
|
||||
"""auth_keys_path=None (--no-auth): no pubkey required, reaches proxy layer."""
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", _mock_no_browser)
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", _mock_no_browser)
|
||||
|
||||
client, server = _pair()
|
||||
t = threading.Thread(
|
||||
@@ -421,7 +421,7 @@ class TestResponseEncoding:
|
||||
"data": {"items": [{"url": f"https://example.com/{i}", "title": f"Tab {i}"} for i in range(300)]}}
|
||||
host_path = tmp_path / "native.sock"
|
||||
host = _FakeNativeHost(host_path, big)
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", lambda *_a, **_k: str(host_path))
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", lambda *_a, **_k: str(host_path))
|
||||
|
||||
client, server = _pair()
|
||||
t = _spawn(server, None) # no auth
|
||||
@@ -446,7 +446,7 @@ class TestResponseEncoding:
|
||||
big = {"id": "y", "success": True, "data": {"items": list(range(500))}}
|
||||
host_path = tmp_path / "native2.sock"
|
||||
host = _FakeNativeHost(host_path, big)
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", lambda *_a, **_k: str(host_path))
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", lambda *_a, **_k: str(host_path))
|
||||
|
||||
client, server = _pair()
|
||||
t = _spawn(server, None)
|
||||
@@ -467,7 +467,7 @@ class TestResponseEncoding:
|
||||
"data": {"items": [{"url": f"https://e/{i}"} for i in range(300)]}}
|
||||
host_path = tmp_path / "native3.sock"
|
||||
host = _FakeNativeHost(host_path, big)
|
||||
monkeypatch.setattr("browser_cli.client._resolve_socket", lambda *_a, **_k: str(host_path))
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", lambda *_a, **_k: str(host_path))
|
||||
|
||||
client, server = _pair()
|
||||
t = threading.Thread(
|
||||
@@ -489,3 +489,42 @@ class TestResponseEncoding:
|
||||
client.close()
|
||||
host.close()
|
||||
t.join(timeout=2)
|
||||
|
||||
# ── async serve path ─────────────────────────────────────────────────────────
|
||||
|
||||
def test_async_handle_client_sends_challenge_and_proxies_no_auth(monkeypatch):
|
||||
"""Async TCP handler mirrors the sync challenge + proxy error path."""
|
||||
import asyncio
|
||||
from browser_cli.commands import serve as serve_mod
|
||||
|
||||
async def run():
|
||||
monkeypatch.setattr("browser_cli.client.targets.resolve_socket", _mock_no_browser)
|
||||
|
||||
async def handle(reader, writer):
|
||||
await serve_mod._async_handle_client(
|
||||
reader,
|
||||
writer,
|
||||
("127.0.0.1", 9999),
|
||||
None,
|
||||
None,
|
||||
True,
|
||||
asyncio.Semaphore(64),
|
||||
)
|
||||
|
||||
server = await asyncio.start_server(handle, "127.0.0.1", 0)
|
||||
host, port = server.sockets[0].getsockname()
|
||||
async with server:
|
||||
reader, writer = await asyncio.open_connection(host, port)
|
||||
challenge = json.loads(await serve_mod._async_recv_all(reader))
|
||||
assert challenge["type"] == "challenge"
|
||||
|
||||
msg = {"id": "x", "command": "tabs.list", "args": {}, "user_agent": FAKE_UA}
|
||||
await serve_mod._async_framed_send(writer, json.dumps(msg).encode())
|
||||
resp = json.loads(await serve_mod._async_recv_all(reader))
|
||||
writer.close()
|
||||
await writer.wait_closed()
|
||||
|
||||
assert resp["success"] is False
|
||||
assert "browser" in resp["error"].lower() or "connected" in resp["error"].lower()
|
||||
|
||||
asyncio.run(run())
|
||||
|
||||
Reference in New Issue
Block a user