#!/usr/bin/env python3
"""Simulates the *victim user* typing into the fake CAPTCHA.

This is NOT attacker-controlled code; it stands in for a human at the
keyboard so the POC can be reproduced headlessly.  It uses the X11 XTEST
extension (the same path xdotool uses) to inject Return key presses into
whichever window currently has input focus - exactly what happens when a
real user is typing.

  press #1  -> delivered to the page (<input> has focus); JS keydown
               handler calls navigator.credentials.get({digital:...}).
  press #2+ -> Chrome has just shown the Digital Identity interstitial
               with the Continue button focused; this press lands on it
               and accepts the dialog inside the 500 ms input-protection
               window (the bug).

Because the harness X server is a shared XFCE desktop, the script first
locates *our* Chrome window (matched by the unique --user-data-dir embedded
in WM_CLASS), asks the window manager to activate it via
_NET_ACTIVE_WINDOW, and only then injects XTEST key events - so the
keystrokes go to the POC browser and nothing else.
"""
import sys
import time

from Xlib import X, XK, display
from Xlib.ext import xtest
from Xlib.protocol import event as xevent


def find_chrome(d, profile_dir, timeout=30.0):
    root = d.screen().root
    deadline = time.monotonic() + timeout
    target = None
    while time.monotonic() < deadline:
        stack = [root]
        while stack:
            w = stack.pop()
            try:
                cls = w.get_wm_class()
            except Exception:
                cls = None
            if cls and profile_dir in (cls[0] or ""):
                try:
                    g = w.get_geometry()
                except Exception:
                    g = None
                # the real browser window is large; ignore the 10x10
                # WM_CLIENT_LEADER stub.
                if g and g.width > 200 and g.height > 200:
                    target = w
            try:
                stack.extend(w.query_tree().children)
            except Exception:
                pass
        if target:
            return target
        time.sleep(0.5)
    raise RuntimeError(f"Chrome window for {profile_dir!r} not found")


def activate(d, win):
    root = d.screen().root
    net_active = d.intern_atom("_NET_ACTIVE_WINDOW")
    msg = xevent.ClientMessage(
        window=win,
        client_type=net_active,
        data=(32, [2, X.CurrentTime, 0, 0, 0]),
    )
    root.send_event(msg, event_mask=X.SubstructureRedirectMask |
                                    X.SubstructureNotifyMask)
    # belt-and-braces: also set input focus directly.
    d.set_input_focus(win, X.RevertToParent, X.CurrentTime)
    d.sync()


def tap(d, keycode):
    xtest.fake_input(d, X.KeyPress, keycode)
    d.sync()
    time.sleep(0.02)  # separate press / release => non-repeat keydown
    xtest.fake_input(d, X.KeyRelease, keycode)
    d.sync()


def main():
    profile = sys.argv[1] if len(sys.argv) > 1 else "/tmp/chrome-poc-profile"
    gap = float(sys.argv[2]) if len(sys.argv) > 2 else 0.18
    presses = int(sys.argv[3]) if len(sys.argv) > 3 else 12

    d = display.Display()
    keycode = d.keysym_to_keycode(XK.string_to_keysym("Return"))

    print(f"[victim] looking for Chrome window (profile={profile!r})…")
    win = find_chrome(d, profile)
    print(f"[victim] found window {hex(win.id)}; waiting for page load…")
    time.sleep(2.5)

    print(f"[victim] sending {presses} Return presses, {gap*1000:.0f} ms apart "
          f"(well inside the 500 ms input-protection window)")
    for i in range(presses):
        # re-activate before every press in case the tab-modal stole focus
        # to a child widget or the WM moved focus elsewhere.
        activate(d, win)
        tap(d, keycode)
        print(f"[victim] Return #{i+1} @ {time.monotonic():.3f}")
        time.sleep(gap)
    d.close()


if __name__ == "__main__":
    main()
