WebExtension manifest v3 support

main
Elbert Alias 2 years ago
parent dad6e19c98
commit 6d3ba54fa9

2
.gitignore vendored

@ -20,4 +20,4 @@ tags.*
/nbproject/private/ /nbproject/private/
src/out.json src/out.json
keys.json keys.json

@ -17,7 +17,8 @@ if (!version) {
;[ ;[
'./src/package.json', './src/package.json',
'./src/drivers/npm/package.json', './src/drivers/npm/package.json',
'./src/drivers/webextension/manifest.json', './src/drivers/webextension/manifest-v2.json',
'./src/drivers/webextension/manifest-v3.json',
].forEach((file) => { ].forEach((file) => {
const json = JSON.parse(fs.readFileSync(file)) const json = JSON.parse(fs.readFileSync(file))
@ -26,8 +27,34 @@ if (!version) {
fs.writeFileSync(file, JSON.stringify(json, null, 2)) fs.writeFileSync(file, JSON.stringify(json, null, 2))
}) })
const zip = new Zip() fs.copyFileSync(
`./src/drivers/webextension/manifest.json`,
'./src/drivers/webextension/manifest.bak.json'
)
fs.copyFileSync(
`./src/drivers/webextension/manifest-v2.json`,
'./src/drivers/webextension/manifest.json'
)
let zip = new Zip()
zip.addLocalFolder('./src/drivers/webextension', '')
zip.writeZip('./build/webextension-v2.zip')
fs.copyFileSync(
`./src/drivers/webextension/manifest-v3.json`,
'./src/drivers/webextension/manifest.json'
)
zip = new Zip()
zip.addLocalFolder('./src/drivers/webextension', '') zip.addLocalFolder('./src/drivers/webextension', '')
zip.writeZip('./build/webextension.zip') zip.writeZip('./build/webextension-v3.zip')
fs.copyFileSync(
`./src/drivers/webextension/manifest.bak.json`,
'./src/drivers/webextension/manifest.json'
)

@ -0,0 +1,15 @@
const fs = require('fs')
const version = process.argv[2]
if (!version) {
// eslint-disable-next-line no-console
console.error(`No manifest version specified.`)
process.exit(1)
}
fs.copyFileSync(
`./src/drivers/webextension/manifest-${version}.json`,
'./src/drivers/webextension/manifest.json'
)

@ -17,13 +17,14 @@
"terminal-overwrite": "^2.0.1" "terminal-overwrite": "^2.0.1"
}, },
"scripts": { "scripts": {
"link": "node ./bin/link.js", "link": "node ./bin/link.js; node ./bin/manifest.js v3",
"lint": "eslint src/**/*.{js,json}", "lint": "eslint src/**/*.{js,json}",
"lint:fix": "eslint --fix src/**/*.{js,json}", "lint:fix": "eslint --fix src/**/*.{js,json}",
"validate": "yarn run lint && jsonlint -qV ./schema.json ./src/technologies/ && node ./bin/validate.js", "validate": "yarn run lint && jsonlint -qV ./schema.json ./src/technologies/ && node ./bin/validate.js",
"convert": "node --no-warnings ./bin/convert.js", "convert": "node --no-warnings ./bin/convert.js",
"prettify": "jsonlint -si --trim-trailing-commas --enforce-double-quotes ./src/categories.json ./src/technologies/*.json", "prettify": "jsonlint -si --trim-trailing-commas --enforce-double-quotes ./src/categories.json ./src/technologies/*.json",
"build": "yarn run link && yarn run validate && yarn run prettify && yarn run convert && node ./bin/build.js", "build": "yarn run link && yarn run validate && yarn run prettify && yarn run convert && node ./bin/build.js",
"build:safari": "xcrun safari-web-extension-converter --swift --project-location build --force src/drivers/webextension" "build:safari": "xcrun safari-web-extension-converter --swift --project-location build --force src/drivers/webextension",
"manifest": "node ./bin/manifest.js"
} }
} }

@ -740,6 +740,12 @@ body.dynamic-icon .category__heading:hover .category__pin {
margin-top: 1.5rem; margin-top: 1.5rem;
} }
.body__options {
background: var(--color-secondary);
max-width: 600px;
margin: 0 auto;
}
.options { .options {
background: var(--color-secondary); background: var(--color-secondary);
color: var(--color-text); color: var(--color-text);

@ -0,0 +1,6 @@
/* globals chrome, importScripts */
importScripts(chrome.runtime.getURL('js/wappalyzer.js'))
importScripts(chrome.runtime.getURL('js/utils.js'))
importScripts(chrome.runtime.getURL('js/driver.js'))
importScripts(chrome.runtime.getURL('js/lib/network.js'))

@ -71,7 +71,7 @@ const Driver = {
ads: [], ads: [],
} }
chrome.browserAction.setBadgeBackgroundColor({ color: '#6B39BD' }, () => {}) chrome.action.setBadgeBackgroundColor({ color: '#6B39BD' }, () => {})
chrome.webRequest.onCompleted.addListener( chrome.webRequest.onCompleted.addListener(
Driver.onWebRequestComplete, Driver.onWebRequestComplete,
@ -742,7 +742,7 @@ const Driver = {
} }
tabs.forEach(({ id: tabId }) => { tabs.forEach(({ id: tabId }) => {
chrome.browserAction.setBadgeText( chrome.action.setBadgeText(
{ {
tabId, tabId,
text: text:
@ -753,7 +753,7 @@ const Driver = {
() => {} () => {}
) )
chrome.browserAction.setIcon( chrome.action.setIcon(
{ {
tabId, tabId,
path: chrome.runtime.getURL( path: chrome.runtime.getURL(
@ -823,11 +823,7 @@ const Driver = {
// eslint-disable-next-line no-async-promise-executor // eslint-disable-next-line no-async-promise-executor
new Promise(async (resolve) => { new Promise(async (resolve) => {
const response = await fetch( const response = await fetch(
`http${secure ? 's' : ''}://${hostname}/robots.txt`, `http${secure ? 's' : ''}://${hostname}/robots.txt`
{
redirect: 'follow',
mode: 'no-cors',
}
) )
if (!response.ok) { if (!response.ok) {

@ -148,9 +148,13 @@
} }
function parseHostnameFromUrl(url) { function parseHostnameFromUrl(url) {
const parser = document.createElement('a') try {
parser.href = url const { hostname } = new URL(url)
return parser.hostname
return hostname
} catch {
return ''
}
} }
function hasDomain(url, domain) { function hasDomain(url, domain) {

@ -170,11 +170,12 @@ function getCsv() {
} }
function csvEscape(value = '') { function csvEscape(value = '') {
console.log(value)
if (Array.isArray(value)) { if (Array.isArray(value)) {
value = value value = value
.flat() .flat()
.slice(0, 10) .slice(0, 10)
.map((value) => csvEscape(value.replace(/ ; /g, ' : '))) .map((value) => csvEscape(String(value).replace(/ ; /g, ' : ')))
.join(' ; ') .join(' ; ')
} }

@ -2,6 +2,18 @@
/* eslint-env browser */ /* eslint-env browser */
/* globals chrome */ /* globals chrome */
// Manifest v2 polyfill
if (chrome.runtime.getManifest().manifest_version === 2) {
chrome.action = chrome.browserAction
chrome.storage.sync = {
get: (...args) =>
new Promise((resolve) => chrome.storage.local.get(...args, resolve)),
set: (...args) =>
new Promise((resolve) => chrome.storage.local.set(...args, resolve)),
}
}
const Utils = { const Utils = {
agent: chrome.runtime.getURL('/').startsWith('moz-') agent: chrome.runtime.getURL('/').startsWith('moz-')
? 'firefox' ? 'firefox'
@ -43,7 +55,7 @@ const Utils = {
*/ */
async getOption(name, defaultValue = null) { async getOption(name, defaultValue = null) {
try { try {
const option = await Utils.promisify(chrome.storage.local, 'get', name) const option = await Utils.promisify(chrome.storage.sync, 'get', name)
if (option[name] !== undefined) { if (option[name] !== undefined) {
return option[name] return option[name]
@ -63,7 +75,7 @@ const Utils = {
*/ */
async setOption(name, value) { async setOption(name, value) {
try { try {
await Utils.promisify(chrome.storage.local, 'set', { await Utils.promisify(chrome.storage.sync, 'set', {
[name]: value, [name]: value,
}) })
} catch (error) { } catch (error) {

@ -0,0 +1,93 @@
{
"name": "Wappalyzer - Technology profiler",
"short_name": "Wappalyzer",
"author": "Wappalyzer",
"homepage_url": "https://www.wappalyzer.com/",
"description": "Identify web technologies",
"version": "6.10.40",
"default_locale": "en",
"manifest_version": 3,
"icons": {
"16": "images/icon_16.png",
"19": "images/icon_19.png",
"32": "images/icon_32.png",
"38": "images/icon_38.png",
"64": "images/icon_64.png",
"128": "images/icon_128.png",
"256": "images/icon_256.png",
"512": "images/icon_512.png",
"1024": "images/icon_1024.png"
},
"action": {
"default_icon": {
"16": "images/icon_16.png",
"19": "images/icon_19.png",
"32": "images/icon_32.png",
"38": "images/icon_38.png",
"64": "images/icon_64.png",
"128": "images/icon_128.png",
"256": "images/icon_256.png",
"512": "images/icon_512.png",
"1024": "images/icon_1024.png"
},
"default_title": "Wappalyzer",
"default_popup": "html/popup.html"
},
"background": {
"service_worker": "js/background.js"
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"js/content.js"
],
"run_at": "document_idle"
},
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"js/lib/iframe.js"
],
"run_at": "document_start",
"all_frames": true
}
],
"web_accessible_resources": [
{
"resources": [
"js/js.js",
"js/dom.js"
],
"matches": [
"http://*/*",
"https://*/*"
]
}
],
"options_page": "html/options.html",
"permissions": [
"cookies",
"storage",
"scripting",
"tabs",
"webRequest",
"webNavigation"
],
"host_permissions": [
"http://*/*",
"https://*/*"
],
"optional_permissions": [
"downloads"
],
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
}