function startHandshake() {
    /* With `once` the listener is removed before DOMNodeInserted is dispatched by appendChild,
     * otherwise a same-origin parent page could use it to spoof the handshake. */
    window::on(handshakeId, handshaker, { capture: true, once: true });
    inject({
      code: `(${VMInitInjection}(${IS_FIREFOX},'${handshakeId}','${vaultId}'))()`
        + `\n//# sourceURL=${VM_UUID}sandbox/injected-web.js`,
    });
    // Clean up in case CSP prevented the script from running
    window::off(handshakeId, handshaker, true);
  }
A page can read our script's textContent in a same-origin iframe via DOMNodeRemoved event.
Directly preventing it would require redefining ~20 DOM methods in the parent.
Instead, we'll send the ids via a temporary handshakeId event, to which the web-bridge
will listen only during its initial phase using vault-protected DOM methods.
TODO: simplify this when strict_min_version >= 63 (attachShadow in FF)