Download source code of browser extensions for Firefox and Chrome

· forensicks's blog


From a web page on from Firefox Browser’s Add-ons site or the Chrome Web Store

Open up the Developer Tools > Console, and copy-paste this snippet below:

  1(function () {
  2  function getExtName() {
  3    const ogTitle = document.querySelector(
  4      'meta[property="og-title"]'
  5    )?.content; // Firefox
  6    const microformatName = document.querySelector(
  7      'meta[itemprop="name"]'
  8    )?.value; // New Chrome
  9    const schemaDotOrgName = JSON.parse(
 10      document.querySelector('script[type="application/ld+json"]')?.innerHTML 
 11||
 12        "{}"
 13    )?.name; // Old Chrome
 14    const title = `${
 15      microformatName || schemaDotOrgName || ogTitle || document.title
 16    }`
 17      .trim()
 18      .replace(/ - .*$/, "")
 19      .replace(/ – .*$/, "")
 20      .trim();
 21  }
 22
 23  function saveAs(blob, name, type) {
 24    const newBlob = new Blob([blob], {
 25      type: type || "application/octet-stream",
 26    });
 27
 28    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
 29      window.navigator.msSaveOrOpenBlob(newBlob, name);
 30      return;
 31    }
 32
 33    const data = window.URL.createObjectURL(newBlob);
 34    const link = document.createElement("a");
 35    link.href = data;
 36    console.log("dataa", data, name);
 37    link.download = name;
 38    link.dispatchEvent(new MouseEvent("click"));
 39    link.click();
 40    setTimeout(() => {
 41      URL.revokeObjectURL(data);
 42    }, 3000);
 43  }
 44
 45  const parseUrl = (url) =>
 46    url instanceof URL ? url : new URL(url, window.location.origin);
 47
 48  function saveLink(url, overrides = {}) {
 49    const { origin, href, pathname, protocol } = parseUrl(url);
 50    const safeFn = href.split("//")[1].replace("/", "__");
 51    const currentExtension = pathname.split(".").slice(-1)[0];
 52    const newExtension =
 53      overrides && "extension" in overrides ? overrides.extension : "";
 54    const anchor = document.createElement("a");
 55    anchor.style = "display:none !important";
 56    anchor.id = `__extdl_${Math.random()}__`;
 57    console.log({ newExtension, safeFn, currentExtension });
 58    if ("download" in anchor) {
 59      anchor.download = safeFn;
 60      if (newExtension) {
 61        const safeExtension = overrides.extension.replace(".", "");
 62        anchor.download = `${safeFn.substr(
 63          0,
 64          safeFn.lastIndexOf(".")
 65        )}.${safeExtension}`;
 66      }
 67    }
 68    anchor.href = href;
 69    document.body.appendChild(anchor);
 70    setTimeout(() => {
 71      anchor.click();
 72      anchor.remove();
 73    }, 100);
 74  }
 75
 76  function saveExtBySelector(selector, href, overrides) {
 77    const dlUrl = href || document.querySelector(selector)?.href;
 78    if (!dlUrl) {
 79      console.warn(`Could not find download link by $('${selector}') on 
 80page`);
 81      return;
 82    }
 83    const parsedDlUrl = new URL(
 84      dlUrl,
 85      window.location.origin || "https://fake.ng"
 86    );
 87    console.log(`Downloading ${parsedDlUrl} …`);
 88    saveLink(parsedDlUrl, overrides);
 89    saveLink(parsedDlUrl, { extension: ".zip" });
 90    const extName = getExtName();
 91    alert(`Downloading ${extName} …`);
 92    return parsedDlUrl;
 93  }
 94
 95  function saveFirefoxExt(url, overrides) {
 96    return saveExtBySelector("[href*='.xpi']", url, overrides);
 97  }
 98
 99  function saveChromeExt(url, overrides) {
100    return saveExtBySelector("[href*='.crx']", url, overrides);
101  }
102
103  function saveFirefoxExtMeta(url, overrides = {}) {
104    const { origin, href, pathname, protocol } = parseUrl(url);
105    const extName = getExtName();
106    const safeFn = href.split("//")[1].replace("/", "__");
107    const targetUrl = `data:text/html,<a href="${
108      window.location.href
109    }">${extName}</a>
110  <p>saved to <code>${safeFn}.meta.json</code></p>
111  <pre>
112  ${JSON.stringify(meta, null, 2)}
113  </pre>`;
114
115    saveAs(
116      `${JSON.stringify(meta, null, 2)}`,
117      `${safeFn}.meta.json`,
118      "data:application/json"
119    );
120
121    setTimeout(() => {
122      self.window.top.close();
123    }, 10000);
124    setTimeout(() => {
125      window.location.href = targetUrl;
126    }, 5000);
127  }
128
129  function downloadExtension(url, overrides) {
130    saveFirefoxExt(url, overrides);
131    // const firefoxExtUrl = saveFirefoxExt(url, overrides);
132    // saveFirefoxExtMeta(firefoxExtUrl, overrides);
133    saveChromeExt(url, overrides);
134  }
135
136  downloadExtension(window.location.href);
137})();