Update web installer for fastboot.js updates
Some of the API and paths have changed, so this needs to be updated accordingly. The most prominent change is the removal of BlobStore and downloading support from fastboot.js, because a fastboot library should not be responsible for downloading files.
This commit is contained in:
parent
3c2c76dfdf
commit
890abfdaff
@ -7,7 +7,7 @@ export PATH="$PWD/node_modules/.bin:$PATH"
|
||||
|
||||
rm -rf static_tmp
|
||||
cp -a static static_tmp
|
||||
rm -rf static_tmp/js/fastboot/{!(dist),dist/!(fastboot.min.js|libs)}
|
||||
rm -rf static_tmp/js/fastboot/{!(dist),dist/!(fastboot.min.mjs|libs)}
|
||||
|
||||
for file in static_tmp/**/*.@(json|webmanifest); do
|
||||
json_reformat -m < "$file" | sponge "$file"
|
||||
|
@ -26,8 +26,8 @@
|
||||
<link rel="stylesheet" href="/grapheneos.css?29"/>
|
||||
<link rel="manifest" href="/manifest.webmanifest"/>
|
||||
<link rel="license" href="/LICENSE.txt"/>
|
||||
<script type="module" src="/js/fastboot/dist/fastboot.min.js?0"></script>
|
||||
<script type="module" src="/js/web-install.js?4"></script>
|
||||
<script type="module" src="/js/fastboot/dist/fastboot.min.mjs?0"></script>
|
||||
<script type="module" src="/js/web-install.js?5"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
|
@ -1,11 +1,98 @@
|
||||
// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT
|
||||
|
||||
import { FastbootDevice, FactoryImages } from "./fastboot/dist/fastboot.min.js?0";
|
||||
import * as fastboot from "./fastboot/dist/fastboot.min.mjs?0";
|
||||
|
||||
const RELEASES_URL = "https://releases.grapheneos.org";
|
||||
|
||||
let device = new FastbootDevice();
|
||||
let lastReleaseZip = null;
|
||||
const CACHE_DB_NAME = "BlobStore";
|
||||
const CACHE_DB_VERSION = 1;
|
||||
|
||||
class BlobStore {
|
||||
constructor() {
|
||||
this.db = null;
|
||||
}
|
||||
|
||||
async _wrapReq(request, onUpgrade = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.onsuccess = () => {
|
||||
resolve(request.result);
|
||||
};
|
||||
request.oncomplete = () => {
|
||||
resolve(request.result);
|
||||
};
|
||||
request.onerror = (event) => {
|
||||
reject(event);
|
||||
};
|
||||
|
||||
if (onUpgrade !== null) {
|
||||
request.onupgradeneeded = onUpgrade;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async init() {
|
||||
if (this.db === null) {
|
||||
this.db = await this._wrapReq(
|
||||
indexedDB.open(CACHE_DB_NAME, CACHE_DB_VERSION),
|
||||
(event) => {
|
||||
let db = event.target.result;
|
||||
db.createObjectStore("files", { keyPath: "name" });
|
||||
/* no index needed for such a small database */
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async saveFile(name, blob) {
|
||||
this.db.transaction(["files"], "readwrite").objectStore("files").add({
|
||||
name: name,
|
||||
blob: blob,
|
||||
});
|
||||
}
|
||||
|
||||
async loadFile(name) {
|
||||
try {
|
||||
let obj = await this._wrapReq(
|
||||
this.db.transaction("files").objectStore("files").get(name)
|
||||
);
|
||||
return obj.blob;
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async close() {
|
||||
this.db.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the file from the given URL and saves it to this BlobStore.
|
||||
*
|
||||
* @param {string} url - URL of the file to download.
|
||||
* @returns {blob} Blob containing the downloaded data.
|
||||
*/
|
||||
async download(url) {
|
||||
let filename = url.split("/").pop();
|
||||
let blob = await this.loadFile(filename);
|
||||
if (blob === null) {
|
||||
console.log(`Downloading ${url}`);
|
||||
let resp = await fetch(new Request(url));
|
||||
blob = await resp.blob();
|
||||
console.log("File downloaded, saving...");
|
||||
await this.saveFile(filename, blob);
|
||||
console.log("File saved");
|
||||
} else {
|
||||
console.log(
|
||||
`Loaded ${filename} from blob store, skipping download`
|
||||
);
|
||||
}
|
||||
|
||||
return blob;
|
||||
}
|
||||
}
|
||||
|
||||
let device = new fastboot.FastbootDevice();
|
||||
let blobStore = new BlobStore();
|
||||
|
||||
async function ensureConnected(setProgress) {
|
||||
console.log(device.device);
|
||||
@ -23,36 +110,50 @@ async function unlockBootloader(setProgress) {
|
||||
return "Bootloader unlocked.";
|
||||
}
|
||||
|
||||
async function downloadRelease(setProgress) {
|
||||
await ensureConnected(setProgress);
|
||||
|
||||
setProgress("Getting device model...");
|
||||
async function getLatestRelease() {
|
||||
let product = await device.getVariable("product");
|
||||
setProgress("Finding latest release...");
|
||||
|
||||
let metadataResp = await fetch(`${RELEASES_URL}/${product}-stable`);
|
||||
let metadata = await metadataResp.text();
|
||||
let releaseId = metadata.split(" ")[0];
|
||||
|
||||
return `${product}-factory-${releaseId}.zip`;
|
||||
}
|
||||
|
||||
async function downloadRelease(setProgress) {
|
||||
await ensureConnected(setProgress);
|
||||
|
||||
setProgress("Finding latest release...");
|
||||
let latestZip = await getLatestRelease();
|
||||
|
||||
// Download and cache the zip as a blob
|
||||
setProgress(`Downloading ${releaseId} release for ${product}...`);
|
||||
lastReleaseZip = `${product}-factory-${releaseId}.zip`;
|
||||
await FactoryImages.downloadZip(`${RELEASES_URL}/${lastReleaseZip}`);
|
||||
return `Downloaded ${releaseId} release for ${product}.`;
|
||||
setProgress(`Downloading ${latestZip}...`);
|
||||
await blobStore.init();
|
||||
await blobStore.download(`${RELEASES_URL}/${latestZip}`);
|
||||
return `Downloaded ${latestZip} release.`;
|
||||
}
|
||||
|
||||
async function flashRelease(setProgress) {
|
||||
await ensureConnected(setProgress);
|
||||
|
||||
// Need to do this again because the user may not have clicked download if
|
||||
// it was cached
|
||||
setProgress("Finding latest release...");
|
||||
let latestZip = await getLatestRelease();
|
||||
await blobStore.init();
|
||||
let blob = await blobStore.loadFile(latestZip);
|
||||
if (blob === null) {
|
||||
throw new Error("You need to download a release first!");
|
||||
}
|
||||
|
||||
setProgress("Flashing release...");
|
||||
await FactoryImages.flashZip(device, lastReleaseZip, (action, partition) => {
|
||||
let userPartition = partition == "avb_custom_key" ? "verified boot key" : partition;
|
||||
if (action == "unpack") {
|
||||
setProgress(`Unpacking image: ${userPartition}`);
|
||||
} else {
|
||||
setProgress(`Flashing image: ${userPartition}`);
|
||||
}
|
||||
await fastboot.FactoryImages.flashZip(device, blob, true, (action, item) => {
|
||||
let userAction = fastboot.FactoryImages.USER_ACTION_MAP[action];
|
||||
let userItem = item === "avb_custom_key" ? "verified boot key" : item;
|
||||
setProgress(`${userAction} ${userItem}...`);
|
||||
});
|
||||
return `Flashed ${lastReleaseZip} to device.`;
|
||||
|
||||
return `Flashed ${latestZip} to device.`;
|
||||
}
|
||||
|
||||
async function lockBootloader(setProgress) {
|
||||
@ -83,9 +184,13 @@ function addButtonHook(id, callback) {
|
||||
};
|
||||
}
|
||||
|
||||
FactoryImages.configureZip({
|
||||
// This doesn't really hurt, and because this page is exclusively for web install,
|
||||
// we can tolerate extra logging in the console in case something goes wrong.
|
||||
fastboot.setDebugMode(true);
|
||||
|
||||
fastboot.FactoryImages.configureZip({
|
||||
workerScripts: {
|
||||
inflate: ["/js/fastboot/dist/libs/z-worker-pako.js", "pako_inflate.min.js"],
|
||||
inflate: ["/js/fastboot/dist/vendor/z-worker-pako.js", "pako_inflate.min.js"],
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -7,13 +7,13 @@ export PATH="$PWD/node_modules/.bin:$PATH"
|
||||
|
||||
rm -rf static_tmp
|
||||
cp -a static static_tmp
|
||||
rm -rf static_tmp/js/fastboot/{!(dist),dist/!(fastboot.min.js|libs)}
|
||||
rm -rf static_tmp/js/fastboot/{!(dist),dist/!(fastboot.min.mjs|libs)}
|
||||
|
||||
for file in static_tmp/**/*.@(json|webmanifest); do
|
||||
json_verify < "$file" >/dev/null
|
||||
done
|
||||
|
||||
xmllint --noout static_tmp/**/*.@(html|svg|xml)
|
||||
eslint static_tmp/**/!(fastboot.min|z-worker-pako|pako_inflate.min).js
|
||||
eslint static_tmp/**/!(fastboot.min.m|z-worker-pako.|pako_inflate.min.)js
|
||||
stylelint static_tmp/**/*.css
|
||||
validatornu --Werror --also-check-css --also-check-svg static_tmp/**/*.@(css|html|svg)
|
||||
|
Loading…
x
Reference in New Issue
Block a user