diff --git a/FrameworkDevtools/crxToZip.js b/FrameworkDevtools/crxToZip.js new file mode 100644 index 0000000..23ab364 --- /dev/null +++ b/FrameworkDevtools/crxToZip.js @@ -0,0 +1,55 @@ +/** + * crxToZip + * Copyright (c) 2013 Rob Wu + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +module.exports = (buf) => { + function calcLength(a, b, c, d) { + let length = 0; + + length += a << 0; + length += b << 8; + length += c << 16; + length += d << 24 >>> 0; + return length; + } + + // 50 4b 03 04 + // This is actually a zip file + if (buf[0] === 80 && buf[1] === 75 && buf[2] === 3 && buf[3] === 4) { + return buf; + } + + // 43 72 32 34 (Cr24) + if (buf[0] !== 67 || buf[1] !== 114 || buf[2] !== 50 || buf[3] !== 52) { + throw new Error("Invalid header: Does not start with Cr24"); + } + + // 02 00 00 00 + // or + // 03 00 00 00 + const isV3 = buf[4] === 3; + const isV2 = buf[4] === 2; + + if ((!isV2 && !isV3) || buf[5] || buf[6] || buf[7]) { + throw new Error("Unexpected crx format version number."); + } + + if (isV2) { + const publicKeyLength = calcLength(buf[8], buf[9], buf[10], buf[11]); + const signatureLength = calcLength(buf[12], buf[13], buf[14], buf[15]); + + // 16 = Magic number (4), CRX format version (4), lengths (2x4) + const zipStartOffset = 16 + publicKeyLength + signatureLength; + + return buf.subarray(zipStartOffset, buf.length); + } + // v3 format has header size and then header + const headerSize = calcLength(buf[8], buf[9], buf[10], buf[11]); + const zipStartOffset = 12 + headerSize; + + return buf.subarray(zipStartOffset, buf.length); +}; \ No newline at end of file diff --git a/FrameworkDevtools/main.js b/FrameworkDevtools/main.js index 0f19aa7..01cab0f 100644 --- a/FrameworkDevtools/main.js +++ b/FrameworkDevtools/main.js @@ -1,32 +1,57 @@ -const { app } = require("electron"); -const devtools = require("electron-devtools-installer"); -const fs = require("fs-extra"); +const { session, app } = require("electron"); const path = require("path"); - -// const broadcast = require("@kernel/core/broadcast"); -// // const { OriginalBrowserWindow } = require("@kernel/core/BrowserWindowPatcher"); +const https = require("https"); +const fs = require("fs"); +const devtools = require("electron-devtools-installer"); +const crxToZip = require("./crxToZip"); +const AdmZip = require('adm-zip'); module.exports.default = { - start() { - console.log("Starting FrameworkDevtools"); - app.on("ready", () => { - const enabledDevtools = fs.readJSONSync( - path.join(__dirname, "index.json") - ).options.devtools; - for (const devtool of enabledDevtools) { - devtools - .default(devtools[devtool], { - loadExtensionOptions: { allowFileAccess: true }, - forceDownload: true, - }) - .then((name) => console.log(`Added Extension: ${name}`)) - .catch((err) => - console.error("Failed to add devtools extensions:", err) - ); - } - }); - }, - stop() { - console.log("Restart the app to unload the devtools."); - }, + start() { + console.log("Starting FrameworkDevtools"); + app.on("ready", async () => { + const enabledDevtools = JSON.parse(fs.readFileSync( + path.join(__dirname, "index.json") + )).options.devtools; + + for (const devtool of enabledDevtools) { + // temporary patch until electron supports manifest v3 + if (devtool === 'REACT_DEVELOPER_TOOLS') { + const url = "https://clients2.googleusercontent.com/crx/blobs/Acy1k0YTNVjurDjs0Ykedxwea0PfCT8fzhxRR-IfyKi2e-u8YladfVsFWx-5-_ounQNmgOCKWhCo8omB48nkUKGAts0hmSuZlKlzfjzPuzeJlRDVWcspAMZSmuUN8b65ifrcdPOHDcNkseF6HMOpXQ/extension_4_25_0_0.crx"; + const dir = path.join(__dirname, 'react-devtools'); + + if (!fs.existsSync(dir)) { + const buf = await new Promise((res) => { + https.get(url, (msg) => { + const data = []; + msg.on('data', (chunk) => { + data.push(chunk); + }).on('end', () => { + res(Buffer.concat(data)); + }); + }); + }); + + new AdmZip(crxToZip(buf)) + .extractAllTo(dir); + } + + session.defaultSession.loadExtension(dir); + } else { + devtools + .default(devtools[devtool], { + loadExtensionOptions: { allowFileAccess: true }, + forceDownload: true, + }) + .then((name) => console.log(`Added Extension: ${name}`)) + .catch((err) => + console.error("Failed to add devtools extensions:", err) + ); + } + } + }); + }, + stop() { + console.log("Restart the app to unload the devtools."); + }, }; diff --git a/FrameworkDevtools/package.json b/FrameworkDevtools/package.json index 40c252a..079c08c 100644 --- a/FrameworkDevtools/package.json +++ b/FrameworkDevtools/package.json @@ -1,6 +1,6 @@ { - "dependencies": { - "electron-devtools-installer": "^3.2.0", - "fs-extra": "^10.0.0" - } + "dependencies": { + "adm-zip": "^0.5.10", + "electron-devtools-installer": "^3.2.0" + } } \ No newline at end of file diff --git a/FrameworkDevtools/pnpm-lock.yaml b/FrameworkDevtools/pnpm-lock.yaml new file mode 100644 index 0000000..e22bd9e --- /dev/null +++ b/FrameworkDevtools/pnpm-lock.yaml @@ -0,0 +1,205 @@ +lockfileVersion: 5.4 + +specifiers: + adm-zip: ^0.5.10 + electron-devtools-installer: ^3.2.0 + +dependencies: + adm-zip: 0.5.10 + electron-devtools-installer: 3.2.0 + +packages: + + /adm-zip/0.5.10: + resolution: {integrity: sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==} + engines: {node: '>=6.0'} + dev: false + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: false + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: false + + /concat-map/0.0.1: + resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} + dev: false + + /core-util-is/1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + + /electron-devtools-installer/3.2.0: + resolution: {integrity: sha512-t3UczsYugm4OAbqvdImMCImIMVdFzJAHgbwHpkl5jmfu1izVgUcP/mnrPqJIpEeCK1uZGpt+yHgWEN+9EwoYhQ==} + dependencies: + rimraf: 3.0.2 + semver: 7.3.8 + tslib: 2.4.1 + unzip-crx-3: 0.2.0 + dev: false + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: false + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /immediate/3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: false + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /isarray/1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: false + + /jszip/3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.7 + setimmediate: 1.0.5 + dev: false + + /lie/3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + dependencies: + immediate: 3.0.6 + dev: false + + /lru-cache/6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: false + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: false + + /minimist/1.2.7: + resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} + dev: false + + /mkdirp/0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.7 + dev: false + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /pako/1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + dev: false + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + + /process-nextick-args/2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + + /readable-stream/2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + + /rimraf/3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: false + + /safe-buffer/5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /semver/7.3.8: + resolution: {integrity: sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: false + + /setimmediate/1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + dev: false + + /string_decoder/1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /tslib/2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: false + + /unzip-crx-3/0.2.0: + resolution: {integrity: sha512-0+JiUq/z7faJ6oifVB5nSwt589v1KCduqIJupNVDoWSXZtWDmjDGO3RAEOvwJ07w90aoXoP4enKsR7ecMrJtWQ==} + dependencies: + jszip: 3.10.1 + mkdirp: 0.5.6 + yaku: 0.16.7 + dev: false + + /util-deprecate/1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false + + /yaku/0.16.7: + resolution: {integrity: sha512-Syu3IB3rZvKvYk7yTiyl1bo/jiEFaaStrgv1V2TIJTqYPStSMQVO8EQjg/z+DRzLq/4LIIharNT3iH1hylEIRw==} + dev: false + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false