• 请不要在回答技术问题时复制粘贴 AI 生成的内容
aaa69532
V2EX  ›  程序员

geek-trusted-wheel-events

  •  
  •   aaa69532 · 3h 22m ago · 122 views

    Scroll Events Even the Page Can't Tell Are Fake

    Modern infinite-scroll pages don't load their feed because you asked nicely. Many of them check event.isTrusted on scroll events — the browser-set flag that distinguishes input originating from an actual user (OS input pipeline) from input synthesized by JavaScript (element.dispatchEvent, window.scrollBy). If the event says isTrusted: false, the page simply declines to fetch more content. It's a polite little fence, and it is genuinely hard to jump: by specification, JavaScript cannot set isTrusted on a synthesized event. Period.

    Which creates a fun problem for Scrapewright, an open-source Chrome extension whose scrapers must trigger lazy-loaded content on pages that employ exactly this filter. Programmatic scrollBy is isTrusted: false forever. The solution the project shipped is the most interesting trick in the repo: wheel events dispatched through Chrome DevTools Protocol's Input domain come out the other side with isTrusted: true — because they enter Chrome through the same input pipeline the OS uses.

    The mechanism

    The chain, briefly:

    1. The step script calls $scrollToBottom (a DSL primitive). Normal path first: programmatic scrolling, with stall detection — if content stops growing, programmatic scroll is being filtered.
    2. On stall, the extension transiently attaches the Chrome DevTools Protocol to the tab (chrome.debugger.attach) — this is the extension-debugging API, which shows the user the standard "is being debugged" infobar; nothing hidden.
    3. It issues Input.dispatchMouseEvent with type: 'mouseWheel' and a synthetic deltaY, targeting the tab.
    4. CDP Input.* commands are injected at the browser's input layer. The resulting wheel event travels the same path as your trackpad: input pipeline → renderer → event listeners — with isTrusted: true. IntersectionObserver-driven loaders and trust-checking handlers behave exactly as they do for a human.
    5. The debugger detaches. Attempts are capped (a small budget per $scrollToBottom call) so a hopeless page fails fast instead of grinding.

    So: the only programmatic mechanism that produces a trusted wheel event in Chrome is CDP Input — not because of a bug, but because CDP Input is the browser's programmable front door to the real input pipeline. Synthetic InputEvents from JS are forever untrusted; CDP-injected ones are "real" by construction.

    The nuances that make it a good read

    It only works in an active tab. Input.dispatchMouseEvent into a background tab can hang or do nothing, because Chrome produces compositor frames only for the active tab of the focused window — a separate, architectural throttle. The project therefore pairs CDP input with a tab activation layer (activate the scrape tab, keep it sticky, return the user to their last-clicked tab when the scrape tab closes). Two "unrelated" Chrome behaviors turn out to be one requirement.

    Detection surface is a design decision. Attaching chrome.debugger is visible (infobar) and observable (console.debugger detection tricks exist, Runtime.enable notifications, etc.). The repo deliberately restricts itself to Input.* commands only — no Runtime.*, Network.*, or DOM.* poking — minimizing both footprint and abuse potential. It's a scraping tool that escalates exactly one rung, for exactly one purpose, with a budget.

    It's the fallback, not the default. Ordinary programmatic scroll works on most sites and is faster; the trusted-wheel path exists for the class of sites whose loaders filter on trust. Escalation-on-stall rather than always-on CDP keeps the common path light and the heavy path rare.

    Is this legit?

    The question deserves the same honesty the code has. The isTrusted fence is designed to distinguish "a human is here" from "code is driving." CDP Input deliberately blurs that — that's literally its function, and it's the same mechanism enterprise RPA tools and Google's own Puppeteer (page.mouse.wheel) expose. Scrapewright uses it inside your own browser, on pages your own session can access, to read content you're entitled to read — the ethical weight sits on what you're entitled to, not on the input mechanism. The repo is equally plain about its limits: this is not an anonymity tool, and its stated scope is repeated, targeted extraction, not mass crawling. If you build on it, keep the same line.

    As pure browser engineering, it's a lovely corner of the stack: spec-level security flag → architectural frame-production rule → input-pipeline injection → activation choreography, all cooperating to make one lazy-loaded feed scroll. The whole five-layer anti-throttling stack it lives in is documented in the whitepaper (§9), and it's some of the best practical Chrome-internals writing in any open-source repo this year.

    Repo: github.com/singhand-labs/scrapewright — GPLv3, lib/renderer-activation.js and lib/scroll-ops.js are where to start reading.

    No Comments Yet
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1605 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:39 · PVG 00:39 · LAX 09:39 · JFK 12:39
    ♥ Do have faith in what you're doing.