GoogleChromeLabs / telnet-client

Apache License 2.0
157 stars 15 forks source link

How to use only wbn and web-sign packages to create an swbn for IWA? #27

Closed guest271314 closed 6 months ago

guest271314 commented 7 months ago

Depending on which package counting method is used this library depends on 496 to 514 packages.

It looks like wbn and wbn-sign and imported we wind up with 9 total packages

Assuming we just want to bundle an HTML page and a single .js file - without xterm and so forth, how would we do that using only wbn and wbn-sign?

guest271314 commented 7 months ago

Alright, I figured out how to create the Web Bundle. Having issues creating an IWA.

guest271314 commented 7 months ago

This is what I have so far. Launched with

--install-isolated-web-app-from-file="/home/user/webbundle/signed.swbn" \

and

--install-isolated-web-app-from-url="https://localhost:8443" \

The icon is in chrome://apps yet doesn't appear to be pointing to an IWA URL.

import * as wbn from "wbn";
import * as wbnSign from "wbn-sign";
import * as fs from "node:fs";

const headers = {
  "content-security-policy":
    "base-uri 'none'; default-src 'self'; object-src 'none'; frame-src 'self' https: blob: data:; connect-src 'self' https:; script-src 'self' 'wasm-unsafe-eval'; img-src 'self' https: blob: data:; media-src 'self' https: blob: data:; font-src 'self' blob: data:; require-trusted-types-for 'script'; frame-ancestors 'self';",
  "cross-origin-embedder-policy": "require-corp",
  "cross-origin-opener-policy": "same-origin",
  "cross-origin-resource-policy": "same-origin",
};

const setHeader = (contentType) => {
  return new Headers({ "content-type": contentType, ...headers });
};

const privateKey = wbnSign.parsePemKey(
  fs.readFileSync("ed25519key.pem", "utf-8"),
);

// Web Bundle ID only:
const webBundleId = new wbnSign.WebBundleId(privateKey).serialize();

// With origin, meaning "isolated-app://" combined with Web Bundle ID:
const webBundleIdWithIWAOrigin = new wbnSign.WebBundleId(
  privateKey,
).serializeWithIsolatedWebAppOrigin();

console.log(webBundleId, webBundleIdWithIWAOrigin);

const builder = new wbn.BundleBuilder();

builder.addExchange(
  webBundleIdWithIWAOrigin + "index.html", // URL
  200, // response code
  { "Content-Type": "text/html", ...headers }, // response headers
  fs.readFileSync("index.html"), // response body (string or Uint8Array)
);

builder.addExchange(
  webBundleIdWithIWAOrigin + "script.js", // URL
  200, // response code
  { "Content-Type": "text/javascript", ...headers }, // response headers
  fs.readFileSync("script.js"), // response body (string or Uint8Array)
);

builder.addExchange(
  webBundleIdWithIWAOrigin + "manifest.webmanifest", // URL
  200, // response code
  { "Content-Type": "application/manifest+json", ...headers }, // response headers
  fs.readFileSync("manifest.webmanifest"), // response body (string or Uint8Array)
);

builder.setPrimaryURL(webBundleIdWithIWAOrigin); // entry point URL
//builder.setManifestURL("manifest.webmanifest"); // entry point URL

fs.writeFileSync("out.wbn", builder.createBundle());

const buf = fs.readFileSync("out.wbn");
const bundle = new wbn.Bundle(buf);
const exchanges = [];
for (const url of bundle.urls) {
  const resp = bundle.getResponse(url);
  exchanges.push({
    url,
    status: resp.status,
    headers: resp.headers,
    body: new TextDecoder("utf-8").decode(resp.body),
  });
}
console.log(
  JSON.stringify(
    {
      version: bundle.version, // format version
      exchanges,
    },
    null,
    2,
  ),
);

// Option 1: With the default (`NodeCryptoSigningStrategy`) signing strategy.
const { signedWebBundle } = await new wbnSign.IntegrityBlockSigner(
  buf,
  new wbnSign.NodeCryptoSigningStrategy(privateKey),
).sign();

fs.writeFileSync("signed.swbn", signedWebBundle);
guest271314 commented 6 months ago

Deconstruction of the rollup-plugin-webbundle to use wbn-sign-webcrypto (wbn-sign using Web Cryptography API) and wbn https://github.dev/guest271314/webbundle for use with node, deno, bun.