192 lines
6.7 KiB
JavaScript
192 lines
6.7 KiB
JavaScript
let chromeURLPattern = /^https?:\/\/chrome.google.com\/webstore\/.+?\/([a-z]{32})(?=[\/#?]|$)/;
|
|
let microsoftURLPattern = /^https?:\/\/microsoftedge.microsoft.com\/addons\/detail\/.+?\/([a-z]{32})(?=[\/#?]|$)/;
|
|
let chromeNewURLPattern = /^https?:\/\/chromewebstore.google.com\/detail\/.+?\/([a-z]{32})(?=[\/#?]|$)/;
|
|
|
|
|
|
function getChromeVersion() {
|
|
var pieces = navigator.userAgent.match(/Chrom(?:e|ium)\/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/);
|
|
if (pieces == null || pieces.length != 5) {
|
|
return undefined;
|
|
}
|
|
pieces = pieces.map(piece => parseInt(piece, 10));
|
|
return {
|
|
major: pieces[1],
|
|
minor: pieces[2],
|
|
build: pieces[3],
|
|
patch: pieces[4]
|
|
};
|
|
}
|
|
|
|
function getNaclArch() {
|
|
var nacl_arch = 'arm';
|
|
if (navigator.userAgent.indexOf('x86') > 0) {
|
|
nacl_arch = 'x86-32';
|
|
} else if (navigator.userAgent.indexOf('x64') > 0) {
|
|
nacl_arch = 'x86-64';
|
|
}
|
|
return nacl_arch;
|
|
}
|
|
let currentVersion = getChromeVersion();
|
|
let version = currentVersion.major + "." + currentVersion.minor + "." + currentVersion.build + "." + currentVersion.patch;
|
|
const nacl_arch = getNaclArch();
|
|
|
|
function getTabTitle(title, currentEXTId, url) {
|
|
if (!chromeNewURLPattern.exec(url)) {
|
|
title = title.match(/^(.*[-])/);
|
|
if (title) {
|
|
title = title[0].split(' - ').join("");
|
|
} else {
|
|
title = currentEXTId;
|
|
}
|
|
}
|
|
// Ѐ-ӿ matches cyrillic characters
|
|
return (title).replace(/[&\/\\#,+()$~%.'":*?<>|{}\sЀ-ӿ]/g, '-').replace(/-*$/g, '').replace(/-+/g, '-');
|
|
}
|
|
|
|
function download(downloadAs, tab) {
|
|
|
|
var query = {
|
|
active: true,
|
|
currentWindow: true
|
|
};
|
|
result = chromeURLPattern.exec(tab.url);
|
|
if (!result) {
|
|
result = chromeNewURLPattern.exec(tab.url);
|
|
}
|
|
if (result && result[1]) {
|
|
var name = getTabTitle(tab.title, result[1], tab.url);
|
|
if (downloadAs === "zip") {
|
|
url = `https://clients2.google.com/service/update2/crx?response=redirect&prodversion=${version}&x=id%3D${result[1]}%26installsource%3Dondemand%26uc&nacl_arch=${nacl_arch}&acceptformat=crx2,crx3`;
|
|
convertURLToZip(url, function (urlVal) {
|
|
downloadFile(urlVal, name + ".zip");
|
|
|
|
});
|
|
} else if (downloadAs === "crx") {
|
|
url = `https://clients2.google.com/service/update2/crx?response=redirect&prodversion=${version}&acceptformat=crx2,crx3&x=id%3D${result[1]}%26uc&nacl_arch=${nacl_arch}`;
|
|
downloadFile(url, name + ".crx", result[1] + ".crx");
|
|
}
|
|
}
|
|
var edgeId = microsoftURLPattern.exec(tab.url);
|
|
if (edgeId && edgeId[1] && downloadAs === "crx") {
|
|
var name = getTabTitle(tab.title, edgeId[1], tab.url);
|
|
url = `https://edge.microsoft.com/extensionwebstorebase/v1/crx?response=redirect&prod=chromiumcrx&prodchannel=&x=id%3D${edgeId[1]}%26installsource%3Dondemand%26uc`;
|
|
downloadFile(url, name + ".crx", edgeId[1] + ".crx");
|
|
}
|
|
// });
|
|
}
|
|
|
|
function ArrayBufferToBlob(arraybuffer, callback) {
|
|
|
|
var data = arraybuffer;
|
|
var buf = new Uint8Array(data);
|
|
var publicKeyLength, signatureLength, header, zipStartOffset;
|
|
if (buf[4] === 2) {
|
|
header = 16;
|
|
publicKeyLength = 0 + buf[8] + (buf[9] << 8) + (buf[10] << 16) + (buf[11] << 24);
|
|
signatureLength = 0 + buf[12] + (buf[13] << 8) + (buf[14] << 16) + (buf[15] << 24);
|
|
zipStartOffset = header + publicKeyLength + signatureLength;
|
|
} else {
|
|
publicKeyLength = 0 + buf[8] + (buf[9] << 8) + (buf[10] << 16) + (buf[11] << 24 >>> 0);
|
|
zipStartOffset = 12 + publicKeyLength;
|
|
}
|
|
// 16 = Magic number (4), CRX format version (4), lengths (2x4)
|
|
|
|
return new Blob([
|
|
new Uint8Array(arraybuffer, zipStartOffset)
|
|
], {
|
|
type: 'application/zip'
|
|
});
|
|
}
|
|
|
|
function convertURLToZip(url, callback, xhrProgressListener) {
|
|
var requestUrl = url;
|
|
fetch(requestUrl).then(function (response) {
|
|
return (response.arrayBuffer())
|
|
}).then((res) => {
|
|
var zipFragment = ArrayBufferToBlob(res);
|
|
var reader = new FileReader();
|
|
reader.readAsDataURL(zipFragment);
|
|
reader.onloadend = function () {
|
|
var base64data = reader.result;
|
|
callback(base64data);
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
function downloadFile(url, fileName, currentEXTId = "unknown", _fails = 0) {
|
|
chrome.downloads.download({
|
|
url: url,
|
|
filename: fileName,
|
|
saveAs: true
|
|
}, function () {
|
|
if (chrome.runtime.lastError) {
|
|
if (chrome.runtime.lastError.message === "Invalid filename" && _fails < 1) {
|
|
downloadFile(url, currentEXTId, currentEXTId, _fails + 1);
|
|
} else {
|
|
alert('An error occurred while trying to save ' + fileName + ':\n\n' +
|
|
chrome.runtime.lastError.message);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
|
|
|
|
function onClickEvent(info, tab) {
|
|
|
|
if (info.menuItemId === "crx" || info.menuItemId === "crxmicrosoft") {
|
|
download("crx", tab)
|
|
} else if (info.menuItemId === "zip") {
|
|
download("zip", tab)
|
|
}
|
|
console.log(info)
|
|
|
|
}
|
|
chrome.contextMenus.onClicked.addListener(onClickEvent);
|
|
|
|
|
|
chrome.runtime.setUninstallURL("https://thebyteseffect.com/posts/reason-for-uninstall-crx-extractor/", null);
|
|
chrome.runtime.onInstalled.addListener(function (details) {
|
|
if (details.reason == "install") {
|
|
chrome.tabs.create({
|
|
url: "https://thebyteseffect.com/posts/crx-extractor-features/"
|
|
});
|
|
|
|
}
|
|
const parent = chrome.contextMenus.create({
|
|
'title': 'Download CRX for this extension',
|
|
'contexts': ['all'],
|
|
'id': "parent",
|
|
'documentUrlPatterns': ['https://chrome.google.com/webstore/detail/*', 'https://chromewebstore.google.com/detail/*']
|
|
});
|
|
chrome.contextMenus.create({
|
|
'title': 'Download CRX for this extension',
|
|
'contexts': ['all'],
|
|
id: "crx",
|
|
parentId: parent,
|
|
'documentUrlPatterns': ['https://chrome.google.com/webstore/detail/*', 'https://chromewebstore.google.com/detail/*']
|
|
});
|
|
|
|
chrome.contextMenus.create({
|
|
'title': 'Download CRX for this extension',
|
|
'contexts': ['all'],
|
|
parentId: parent,
|
|
id: "crxmicrosoft",
|
|
'documentUrlPatterns': ['https://microsoftedge.microsoft.com/addons/detail/*']
|
|
});
|
|
chrome.contextMenus.create({
|
|
'title': 'Download ZIP for this extension',
|
|
'contexts': ['all'],
|
|
id: "zip",
|
|
parentId: parent,
|
|
'documentUrlPatterns': ['https://chrome.google.com/webstore/detail/*', 'https://chromewebstore.google.com/detail/*']
|
|
});
|
|
});
|
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
|
download(request.download, request.tab);
|
|
});
|