Jump to content

[UDF] WV2Bridge 3.1 - authenticated, promise-based RPC between a WebView2 page and AutoIt (add-on for my WebView2 UDF)


Recommended Posts

Posted (edited)

Parent topic: WebView2 UDF

An add-on on top of WebView2, using only its public functions: no extra DLL, no COM object of its own, no JSON dependency. Requires AutoIt 3.3.16.1+ and WebView2.au3 0.6.0 or newer - 0.6.1 is bundled in the zip, so the kit runs exactly as extracted.

control-center.thumb.png.b7092079187fc28b5db2552ffc5f5302.png

The problem

The UDF gives you a queue of web messages. Every project ends up with a Switch $sData, a hand-made reply convention and no protection against a page that is not yours. WV2Bridge replaces that with named functions and promises.

JavaScript side

Nothing to include in the page: the script is injected before the page's own code.

const sum  = await au3.call("sum", 40, 2);              // "42"
const info = await au3.json("sysinfo");                 // parsed JSON
await au3.call("save", { name: "x", tags: [1, 2] });    // objects travel as JSON
au3.send("scroll", y);                                  // one way, no answer, no slot held
au3.onJson("stats", s => draw(s.cpu));                  // pushed by AutoIt
try { await au3.call("sum", "x"); } catch (e) { console.log(e.code, e.message); }

AutoIt side

#include "WV2Bridge.au3"

_WV2B_Init($iWV, @ScriptDir & "\web", "app.local")     ; map the folder, inject the bridge, lock the origin
_WV2B_Register("sum", "_H_Sum", 0, 1)                  ; at least 1 argument, checked before your code runs
_WV2_Navigate($iWV, "https://app.local/index.html")

While GUIGetMsg() <> $GUI_EVENT_CLOSE
    _WV2B_Poll()
    Sleep(10)
WEnd
_WV2B_DestroyAll()

Func _H_Sum($aArgs)                                    ; $aArgs[0] = count, $aArgs[1..n]
    Local $f = 0, $v
    For $i = 1 To $aArgs[0]
        $v = _WV2B_ArgNum($aArgs, $i)
        If @error Then Return _WV2B_Fail("argument " & $i & " is not a number", 422)
        $f += $v
    Next
    Return $f                                          ; arrays, Maps, booleans and Binary are encoded for you
EndFunc

What it does

  • Handlers run from _WV2B_Poll() in your main loop, never inside a runtime callback, so they can call _WV2_PrintToPdf, FileSaveDialog, MsgBox... (no $WV2_ERR_BUSY).
  • Authenticated channel. The script is injected with _WV2_AddScriptToExecuteOnDocumentCreated and carries a random 128-bit secret, generated per view with RtlGenRandom. It only exists in the top frame of an allowed origin, keeps the secret in a closure, and captured postMessage at injection time - so a script of your own page can neither read the secret nor watch it leave. A foreign iframe, a page you navigated to by mistake or a script posting to chrome.webview directly cannot call your handlers: those frames are counted and never answered. Answers and pushed events are only posted while the view is still on an allowed origin.
  • Flow control. The page keeps at most 24 calls in flight and has a separate window for one-way frames, which the host releases with an "A|count" acknowledgement once they left the queue. Both windows are clamped to the capacity of the UDF's 64-event ring, so a page cannot ask for a number that guarantees losses, and a drop made by something else is still counted.
  • Deferred answers (_WV2B_Defer / _WV2B_Resolve / _WV2B_Reject), a small scheduler (_WV2B_AddTask), multi-view support with per-view handlers, a hello handler, a logger, statistics, a built-in JSON encoder/decoder and strict base64 helpers (crypt32 accepts input it should reject, so the alphabet, the length and the padding position are validated first).
  • Handle recycling is handled: use _WV2B_Destroy / _WV2B_DestroyAll; a view destroyed behind the library's back is detected and detached.
  • Both shipped programs verify themselves and exit with the number of failures, so they drop into CI:
AutoIt3.exe WV2Bridge.au3                 ->  "86/86 passed"
AutoIt3.exe 01_minimal_rpc.au3 /check     ->  11 assertions through a real page, no click

Measured

Windows 10 19045, AutoIt 3.3.16.1 x86, WebView2.au3 0.6.1, runtime 156.0.4314.58

  • one call at a time: 33.5 ms median per round trip
  • 48 calls pipelined: 1.89 ms per call
  • the origin check (_WV2_GetSource😞 0.115 ms
  • one posted frame: 1.5 ms
  • a reply of 8 MB: arrives whole, 1166 ms
  • 300 au3.send frames: 300 received, 0 dropped
  • 200 calls demanded at once: clamped to 48, 200/200 answered (without the clamp: exactly 64 answered)
  • a hook installed before the injected script: sees 0 frames, the guarded handler is invoked 0 times

The floor is the runtime, not the bridge. If you need many calls, pipeline them (Promise.all) rather than looping.

Limits

  • It does not protect against a script running inside your own trusted origin (XSS): use a CSP, escape what you render, validate every argument. The CSP line that fits a local page is in the header of the file.
  • Handlers are synchronous: a slow handler delays the others. For long work, _WV2B_Defer and answer later.
  • Arguments are strings and cannot contain Chr(31) (stripped). A text field cannot contain Chr(0) either: WebView2 cuts a string message at the first NUL, so the page refuses such an argument and the library turns such a reply into an error instead of a truncated answer. For bytes, return Binary - it travels as base64.
  • With Au3Stripper, list your handlers in #Au3Stripper_Ignore_Funcs (they are called by name).
  • Tested with: Windows 10 19045, AutoIt 3.3.16.1 x86 (the x64 test build runs the same checks), WebView2.au3 0.6.0 and 0.6.1 (every function this add-on calls has the same signature in both), runtime 156.0.4314.58.

Files in the zip

  • WV2Bridge.au3
  • WebView2.au3 (min : 0.6.1, bundled so the relative include resolves)
  • 01_minimal_rpc.au3 (the smallest useful program, self-checking)
  • WV2Bridge_Demo.au3 + web\index.html ("AutoIt Control Center": live CPU/memory traces pushed from AutoIt, process list, file browser, PDF/PNG export, a playground that calls any registered function)
  • WV2Bridge_Quick_Start.pdf (a 15-page booklet: one call end to end, the 19 page members, the AutoIt side, bytes and slow work, what the bridge refuses, flow control with the measured latencies; the programs it prints are cut from the kit's own files by line number, so the PDF cannot drift from the code)
  • README.md
  • CHANGELOG.md
  • MIT LICENSE

The changelog is worth a read: five of the fixes in 3.1 came from measuring the runtime rather than from reading code - the promise of a rejection that was answered as a success (Return f() does not carry @error in AutoIt), base64 that crypt32 happily invents bytes for, a secret a page script could observe, a ring that drops the oldest event when a producer is fast, and a string message cut at Chr(0).

Download

WV2Bridge 3.1 -    WV2Bridge_v3.1.1.zip

  • Self-contained: WebView2.au3 0.6.1 is bundled, so nothing else to download
  • Requires AutoIt 3.3.16.1+ and the WebView2 runtime
  • License: MIT

Quick start: extract the zip anywhere (keep the folder structure), then run WV2Bridge_Demo.au3 for the Control Center, or 01_minimal_rpc.au3 for the smallest example. Both are self-checking: run AutoIt3.exe WV2Bridge.au3 and you should see 86/86 passed.

Feedback, bug reports and questions are welcome in this thread.

Edited by Numeric1
Updated to v3.1.1
From 0 and 1 to the stars, it all starts with binary, Numeric1
 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...