You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

128 lines
3.3 KiB

'use strict'
/* eslint-env browser */
/* globals chrome */
const Content = {
/**
* Initialize content detection.
*/
async init() {
await new Promise((resolve) => setTimeout(resolve, 1000))
Content.port = chrome.runtime.connect({ name: 'content.js' })
Content.port.onMessage.addListener(({ func, args }) => {
const onFunc = `on${func.charAt(0).toUpperCase() + func.slice(1)}`
if (Content[onFunc]) {
Content[onFunc](args)
}
})
try {
// HTML
let html = new XMLSerializer().serializeToString(document)
const chunks = []
const maxCols = 2000
const maxRows = 3000
const rows = html.length / maxCols
for (let i = 0; i < rows; i += 1) {
if (i < maxRows / 2 || i > rows - maxRows / 2) {
chunks.push(html.slice(i * maxCols, (i + 1) * maxCols))
}
}
html = chunks.join('\n')
const language =
document.documentElement.getAttribute('lang') ||
document.documentElement.getAttribute('xml:lang') ||
(await new Promise((resolve) =>
chrome.i18n.detectLanguage(html, ({ languages }) =>
resolve(
languages
.filter(({ percentage }) => percentage >= 75)
.map(({ language: lang }) => lang)[0]
)
)
))
// Script tags
const scripts = Array.from(document.scripts)
.filter(({ src }) => src)
.map(({ src }) => src)
.filter((script) => script.indexOf('data:text/javascript;') !== 0)
// Meta tags
const meta = Array.from(document.querySelectorAll('meta')).reduce(
(metas, meta) => {
const key = meta.getAttribute('name') || meta.getAttribute('property')
if (key) {
metas[key.toLowerCase()] = [meta.getAttribute('content')]
}
return metas
},
{}
)
Content.port.postMessage({
func: 'onContentLoad',
args: [location.href, { html, scripts, meta }, language]
})
Content.port.postMessage({ func: 'getTechnologies' })
} catch (error) {
Content.port.postMessage({ func: 'error', args: [error, 'content.js'] })
}
},
/**
* Callback for fetching technologies.
* @param {Object} technologies
*/
onGetTechnologies(technologies) {
const script = document.createElement('script')
script.onload = () => {
const onMessage = ({ data }) => {
if (!data.wappalyzer || !data.wappalyzer.js) {
return
}
window.removeEventListener('message', onMessage)
Content.port.postMessage({
func: 'analyzeJs',
args: [location.href, data.wappalyzer.js]
})
script.remove()
}
window.addEventListener('message', onMessage)
window.postMessage({
wappalyzer: {
technologies: technologies
.filter(({ js }) => Object.keys(js).length)
.map(({ name, js }) => ({ name, chains: Object.keys(js) }))
}
})
}
script.setAttribute('src', chrome.extension.getURL('js/inject.js'))
document.body.appendChild(script)
}
}
if (/complete|interactive|loaded/.test(document.readyState)) {
Content.init()
} else {
document.addEventListener('DOMContentLoaded', Content.init)
}