CSS domain commands (CSS.enable, CSS.getAllStyleSheets) hang with no response through Target routing

Open
#434 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
25/100
Issue type
Bug
Clarity
Needs clarification
Activity status
Stale
Tech stack
c, ios

Research direction

Start by tracing _rpc_forwardSocketData and the Target routing path, then compare CSS commands with the working domain commands in the reproduction. Check whether the missing response originates in webinspectord or InspectorCSSAgent. Done means CSS.enable, CSS.getAllStyleSheets, and CSS.getStyleSheetText return responses without causing later commands to hang.

Written by the indexing model from the issue text.

Description

Problem

Several CSS domain commands hang indefinitely when sent through the WebSocket proxy. The commands are forwarded to webinspectord but no response is ever relayed back. Worse, the hang corrupts the Target routing pipeline so all subsequent commands on the same connection also hang.

Commands that hang:

  • CSS.enable
  • CSS.getAllStyleSheets
  • CSS.getStyleSheetText

Commands that work fine:

  • CSS.getMatchedStylesForNode
  • CSS.getComputedStyleForNode
  • CSS.getInlineStylesForNode
  • CSS.setStyleText
  • CSS.forcePseudoState
  • All other domain enables: Debugger.enable, Canvas.enable, Animation.enable, Worker.enable
Reproduction

Connect via WebSocket, wait for Target.targetCreated, then send commands wrapped in Target.sendMessageToTarget:

# pip install websocket-client
import json, time, threading, websocket

WS_URL = "ws://localhost:9222/devtools/page/1"
ws = websocket.create_connection(WS_URL, timeout=10)
target_id = None
pending = {}

def read_loop():
    global target_id
    while True:
        try:
            data = ws.recv()
            msg = json.loads(data)
            if msg.get("method") == "Target.targetCreated":
                target_id = msg["params"]["targetInfo"]["targetId"]
                continue
            if msg.get("method") == "Target.dispatchMessageFromTarget":
                inner = json.loads(msg["params"]["message"])
                iid = inner.get("id")
                if iid and iid in pending:
                    pending[iid]["result"] = inner
                    pending[iid]["event"].set()
        except: break

t = threading.Thread(target=read_loop, daemon=True)
t.start()
time.sleep(1)

next_id = [1]
def send(method, params=None, timeout=5):
    iid = next_id[0]; next_id[0] += 1
    inner = {"id": iid, "method": method}
    if params: inner["params"] = params
    evt = threading.Event()
    pending[iid] = {"event": evt, "result": None}
    oid = next_id[0]; next_id[0] += 1
    outer = {"id": oid, "method": "Target.sendMessageToTarget",
             "params": {"targetId": target_id, "message": json.dumps(inner)}}
    ws.send(json.dumps(outer))
    if evt.wait(timeout):
        return pending.pop(iid)["result"]
    pending.pop(iid, None)
    return "TIMEOUT"

# Works fine
print("Runtime.evaluate:", send("Runtime.evaluate", {"expression": "1+1", "returnByValue": True}))
print("Debugger.enable:", send("Debugger.enable"))
print("Debugger.disable:", send("Debugger.disable"))

# Hangs (no response, times out after 5s)
print("CSS.enable:", send("CSS.enable"))

# Connection is now corrupted. This also hangs:
print("Runtime.evaluate after CSS.enable:", send("Runtime.evaluate", {"expression": "2+2", "returnByValue": True}))

ws.close()

Output:

Runtime.evaluate: {"id": 1, "result": {"result": {"type": "number", "value": 2, ...}}}
Debugger.enable: {"id": 3, "result": {}}
Debugger.disable: {"id": 5, "result": {}}
CSS.enable: TIMEOUT
Runtime.evaluate after CSS.enable: TIMEOUT
Environment
  • iOS 17.2 (Simulator, iPhone 15 Pro)
  • ios-webkit-debug-proxy 1.9.2
  • macOS 15.5 / Xcode 26.3
Notes

I understand iwdp is a transparent proxy that forwards messages verbatim via _rpc_forwardSocketData. The bug is likely in webinspectord or WebKit's InspectorCSSAgent when handling commands through the remote debugging path.

Dominant language
C
Stars
6.2k
Forks
482
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from google/ios-webkit-debug-proxy

All issues in google/ios-webkit-debug-proxy

Similar issues

More C issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.