@ -0,0 +1,7 @@
|
|||||||
|
apps.json
|
||||||
|
images/icons/converted/*.png
|
||||||
|
images/icons/*.png
|
||||||
|
images/icons/*.svg
|
||||||
|
js/wappalyzer.js
|
||||||
|
js/iframe.js
|
||||||
|
js/network.js
|
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"github": { "message": "Fork Wappalyzer on GitHub!" },
|
||||||
|
"twitter": { "message": "Follow Wappalyzer on Twitter" },
|
||||||
|
"website": { "message": "Go to wappalyzer.com" },
|
||||||
|
"options": { "message": "Options" },
|
||||||
|
"optionsSave": { "message": "Save options" },
|
||||||
|
"optionsSaved": { "message": "Saved" },
|
||||||
|
"optionUpgradeMessage": { "message": "Tell me about upgrades" },
|
||||||
|
"optionTracking": { "message": "Anonymously send reports on detected applications to wappalyzer.com for research" },
|
||||||
|
"nothingToDo": { "message": "Nothing to do here." },
|
||||||
|
"noAppsDetected": { "message": "No applications detected." },
|
||||||
|
"categoryName1": { "message": "CMS" },
|
||||||
|
"categoryName2": { "message": "Message Board" },
|
||||||
|
"categoryName3": { "message": "Database Manager" },
|
||||||
|
"categoryName4": { "message": "Documentation Tool" },
|
||||||
|
"categoryName5": { "message": "Widget" },
|
||||||
|
"categoryName10": { "message": "Analytics" },
|
||||||
|
"categoryName11": { "message": "Blog" },
|
||||||
|
"categoryName12": { "message": "JavaScript Framework" },
|
||||||
|
"categoryName13": { "message": "Issue Tracker" },
|
||||||
|
"categoryName14": { "message": "Video Player" },
|
||||||
|
"categoryName15": { "message": "Comment System" },
|
||||||
|
"categoryName16": { "message": "Captcha" },
|
||||||
|
"categoryName17": { "message": "Font Script" },
|
||||||
|
"categoryName18": { "message": "Web Framework" },
|
||||||
|
"categoryName19": { "message": "Miscellaneous" },
|
||||||
|
"categoryName20": { "message": "Editor" },
|
||||||
|
"categoryName21": { "message": "LMS" },
|
||||||
|
"categoryName22": { "message": "Web Server" },
|
||||||
|
"categoryName23": { "message": "Cache Tool" },
|
||||||
|
"categoryName24": { "message": "Rich Text Editor" },
|
||||||
|
"categoryName25": { "message": "JavaScript Graphics" },
|
||||||
|
"categoryName26": { "message": "Mobile Framework" },
|
||||||
|
"categoryName27": { "message": "Programming Language" },
|
||||||
|
"categoryName28": { "message": "Operating System" },
|
||||||
|
"categoryName29": { "message": "Search Engine" },
|
||||||
|
"categoryName30": { "message": "Web Mail" },
|
||||||
|
"categoryName31": { "message": "CDN" },
|
||||||
|
"categoryName32": { "message": "Marketing Automation" },
|
||||||
|
"categoryName33": { "message": "Web Server Extension" },
|
||||||
|
"categoryName34": { "message": "Database" },
|
||||||
|
"categoryName35": { "message": "Map" },
|
||||||
|
"categoryName36": { "message": "Advertising Network" },
|
||||||
|
"categoryName37": { "message": "Network Service" },
|
||||||
|
"categoryName38": { "message": "Media Server" },
|
||||||
|
"categoryName39": { "message": "Webcam" },
|
||||||
|
"categoryName40": { "message": "Printer" },
|
||||||
|
"categoryName41": { "message": "Payment Processor" },
|
||||||
|
"categoryName42": { "message": "Tag Manager" },
|
||||||
|
"categoryName43": { "message": "Paywall" },
|
||||||
|
"categoryName44": { "message": "Build/CI System" },
|
||||||
|
"categoryName45": { "message": "SCADA System" },
|
||||||
|
"categoryName46": { "message": "Remote Access" },
|
||||||
|
"categoryName47": { "message": "Development Tool" },
|
||||||
|
"categoryName48": { "message": "Network Storage" },
|
||||||
|
"categoryName49": { "message": "Feed Readers" },
|
||||||
|
"categoryName50": { "message": "Document Management Systems" },
|
||||||
|
"categoryName51": { "message": "Landing Page Builder" },
|
||||||
|
"categoryName52": { "message": "Live Chat" }
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"github": { "message": "¡Forkea Wappalyzer en GitHub!" },
|
||||||
|
"twitter": { "message": "Sigue Wappalyzer en Twitter" },
|
||||||
|
"website": { "message": "Ir a wappalyzer.com" },
|
||||||
|
"options": { "message": "Opciones" },
|
||||||
|
"optionsSave": { "message": "Guardar opciones" },
|
||||||
|
"optionsSaved": { "message": "Guardado" },
|
||||||
|
"optionUpgradeMessage": { "message": "Indicarme actualizaciones" },
|
||||||
|
"optionTracking": { "message": "Enviar informes anónimos sobre las aplicaciones detectadas a wappalyzer.com para análisis" },
|
||||||
|
"nothingToDo": { "message": "Nada que hacer aquí." },
|
||||||
|
"noAppsDetected": { "message": "Aplicaciones no detectadas." },
|
||||||
|
"categoryName1": { "message": "Gestor de Contenido" },
|
||||||
|
"categoryName2": { "message": "Foro" },
|
||||||
|
"categoryName3": { "message": "Gestor de Bases de Datos" },
|
||||||
|
"categoryName4": { "message": "Herramienta de Documentación" },
|
||||||
|
"categoryName5": { "message": "Widget" },
|
||||||
|
"categoryName6": { "message": "Tienda Web" },
|
||||||
|
"categoryName7": { "message": "Galería fotográfica" },
|
||||||
|
"categoryName8": { "message": "Wiki" },
|
||||||
|
"categoryName9": { "message": "Panel de Hosting" },
|
||||||
|
"categoryName10": { "message": "Analítica" },
|
||||||
|
"categoryName11": { "message": "Blog" },
|
||||||
|
"categoryName12": { "message": "Framework JavaScript" },
|
||||||
|
"categoryName13": { "message": "Gestor de Incidencias" },
|
||||||
|
"categoryName14": { "message": "Reproductor de Vídeo" },
|
||||||
|
"categoryName15": { "message": "Sistema de Comentarios" },
|
||||||
|
"categoryName16": { "message": "Captcha" },
|
||||||
|
"categoryName17": { "message": "Tipografía" },
|
||||||
|
"categoryName18": { "message": "Framework Web" },
|
||||||
|
"categoryName19": { "message": "Miscelánea" },
|
||||||
|
"categoryName20": { "message": "Editor" },
|
||||||
|
"categoryName21": { "message": "LMS" },
|
||||||
|
"categoryName22": { "message": "Servidor Web" },
|
||||||
|
"categoryName23": { "message": "Herramienta de Cache" },
|
||||||
|
"categoryName24": { "message": "Editor de Texto Enriquecido" },
|
||||||
|
"categoryName25": { "message": "Gráficos JavaScript" },
|
||||||
|
"categoryName26": { "message": "Framework Móvil" },
|
||||||
|
"categoryName27": { "message": "Lenguaje de programación" },
|
||||||
|
"categoryName28": { "message": "Sistema Operativo" },
|
||||||
|
"categoryName29": { "message": "Motor de Búsqueda" },
|
||||||
|
"categoryName30": { "message": "Correo Web" },
|
||||||
|
"categoryName31": { "message": "CDN" },
|
||||||
|
"categoryName32": { "message": "Automatización de Marketing" },
|
||||||
|
"categoryName33": { "message": "Extensión de Servidor Web" },
|
||||||
|
"categoryName34": { "message": "Base de Datos" },
|
||||||
|
"categoryName35": { "message": "Mapa" },
|
||||||
|
"categoryName36": { "message": "Red de Publicidad" },
|
||||||
|
"categoryName37": { "message": "Network Sevice" },
|
||||||
|
"categoryName38": { "message": "Media Server" },
|
||||||
|
"categoryName39": { "message": "Webcam" },
|
||||||
|
"categoryName40": { "message": "Printer" },
|
||||||
|
"categoryName41": { "message": "Payment Processor" },
|
||||||
|
"categoryName42": { "message": "Tag Manager" },
|
||||||
|
"categoryName43": { "message": "Paywall" },
|
||||||
|
"categoryName44": { "message": "Build/CI System" },
|
||||||
|
"categoryName45": { "message": "SCADA System" },
|
||||||
|
"categoryName46": { "message": "Remote Access" },
|
||||||
|
"categoryName47": { "message": "Development Tool" },
|
||||||
|
"categoryName48": { "message": "Network Storage" },
|
||||||
|
"categoryName49": { "message": "Feed Readers" },
|
||||||
|
"categoryName50": { "message": "Document Management Systems" },
|
||||||
|
"categoryName51": { "message": "Landing Page Builder" },
|
||||||
|
"categoryName52": { "message": "Live Chat" }
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"github": { "message": "Fork Wappalyzer su GitHub!" },
|
||||||
|
"twitter": { "message": "Follow Wappalyzer su Twitter" },
|
||||||
|
"website": { "message": "Vai su wappalyzer.com" },
|
||||||
|
"options": { "message": "Opzioni" },
|
||||||
|
"optionsSave": { "message": "Salva opzioni" },
|
||||||
|
"optionsSaved": { "message": "Salvato" },
|
||||||
|
"optionUpgradeMessage": { "message": "Parlami dell'upgrade" },
|
||||||
|
"optionTracking": { "message": "Inviare anonimamente un report sulle applicazioni rilevate a wappalyzer.com per l'analisi" },
|
||||||
|
"nothingToDo": { "message": "Niente da fare qui." },
|
||||||
|
"noAppsDetected": { "message": "Nessuna applicazione rilevata." },
|
||||||
|
"categoryName1": { "message": "CMS" },
|
||||||
|
"categoryName2": { "message": "Forum" },
|
||||||
|
"categoryName3": { "message": "Gestore di Database" },
|
||||||
|
"categoryName4": { "message": "Strumento di documentazione" },
|
||||||
|
"categoryName5": { "message": "Widget" },
|
||||||
|
"categoryName6": { "message": "eCommerce" },
|
||||||
|
"categoryName7": { "message": "Galleria fotografica" },
|
||||||
|
"categoryName8": { "message": "Wiki" },
|
||||||
|
"categoryName9": { "message": "Pannello Hosting" },
|
||||||
|
"categoryName10": { "message": "Analytics" },
|
||||||
|
"categoryName11": { "message": "Blog" },
|
||||||
|
"categoryName12": { "message": "Framework JavaScript" },
|
||||||
|
"categoryName13": { "message": "Issue Tracker" },
|
||||||
|
"categoryName14": { "message": "Player Video" },
|
||||||
|
"categoryName15": { "message": "Sistema di commenti" },
|
||||||
|
"categoryName16": { "message": "Captcha" },
|
||||||
|
"categoryName17": { "message": "Font Script" },
|
||||||
|
"categoryName18": { "message": "Framework Web" },
|
||||||
|
"categoryName19": { "message": "Miscellanea" },
|
||||||
|
"categoryName20": { "message": "Editor" },
|
||||||
|
"categoryName21": { "message": "LMS" },
|
||||||
|
"categoryName22": { "message": "Web Server" },
|
||||||
|
"categoryName23": { "message": "Cache Tool" },
|
||||||
|
"categoryName24": { "message": "Editor di Testo Ricco" },
|
||||||
|
"categoryName25": { "message": "JavaScript Graphics" },
|
||||||
|
"categoryName26": { "message": "Framework Mobile" },
|
||||||
|
"categoryName27": { "message": "Linguaggio di programmazione" },
|
||||||
|
"categoryName28": { "message": "Sistema Operativo" },
|
||||||
|
"categoryName29": { "message": "Motore di Ricerca" },
|
||||||
|
"categoryName30": { "message": "Web Mail" },
|
||||||
|
"categoryName31": { "message": "CDN" },
|
||||||
|
"categoryName32": { "message": "Marketing Automation" },
|
||||||
|
"categoryName33": { "message": "Estensione Web Server" },
|
||||||
|
"categoryName34": { "message": "Database" },
|
||||||
|
"categoryName35": { "message": "Mappa" },
|
||||||
|
"categoryName36": { "message": "Network Pubblicitario" },
|
||||||
|
"categoryName37": { "message": "Network Service" },
|
||||||
|
"categoryName38": { "message": "Media Server" },
|
||||||
|
"categoryName39": { "message": "Webcam" },
|
||||||
|
"categoryName40": { "message": "Stampante" },
|
||||||
|
"categoryName41": { "message": "Payment Processor" },
|
||||||
|
"categoryName42": { "message": "Tag Manager" },
|
||||||
|
"categoryName43": { "message": "Paywall" },
|
||||||
|
"categoryName44": { "message": "Sistema Build/CI" },
|
||||||
|
"categoryName45": { "message": "SCADA System" },
|
||||||
|
"categoryName46": { "message": "Accesso" },
|
||||||
|
"categoryName47": { "message": "Strumenti di Sviluppo" },
|
||||||
|
"categoryName48": { "message": "Network Storage" },
|
||||||
|
"categoryName49": { "message": "Lettore di Feed" },
|
||||||
|
"categoryName50": { "message": "Sistema di Gestione Documenti" },
|
||||||
|
"categoryName51": { "message": "Landing Page Builder" },
|
||||||
|
"categoryName52": { "message": "Live Chat" }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"github": { "message": "Fork-uiește Wappalyzer pe GitHub!" },
|
||||||
|
"twitter": { "message": "Urmărește Wappalyzer pe Twitter" },
|
||||||
|
"website": { "message": "Mergi la wappalyzer.com" },
|
||||||
|
"options": { "message": "Opțiuni" },
|
||||||
|
"optionsSave": { "message": "Salvează opțiuni" },
|
||||||
|
"optionsSaved": { "message": "Salvat" },
|
||||||
|
"optionUpgradeMessage": { "message": "Anunță-mă dacă sunt actualizări" },
|
||||||
|
"optionTracking": { "message": "Trimite rapoarte anonime despre aplicațiile detectate către wappalyzer.com pentru cercetare" },
|
||||||
|
"nothingToDo": { "message": "Nimic de făcut pe pagina curentă." },
|
||||||
|
"noAppsDetected": { "message": "Nici o aplicație detectată." },
|
||||||
|
"categoryName1": { "message": "CMS" },
|
||||||
|
"categoryName2": { "message": "Forum de discuții" },
|
||||||
|
"categoryName3": { "message": "Manager baze de date" },
|
||||||
|
"categoryName4": { "message": "Unealtă pentru documentare" },
|
||||||
|
"categoryName5": { "message": "Widget" },
|
||||||
|
"categoryName10": { "message": "Analiză trafic web" },
|
||||||
|
"categoryName11": { "message": "Blog" },
|
||||||
|
"categoryName12": { "message": "Framework JavaScript" },
|
||||||
|
"categoryName13": { "message": "Tracker probleme" },
|
||||||
|
"categoryName14": { "message": "Player Video" },
|
||||||
|
"categoryName15": { "message": "Sistem de comentarii" },
|
||||||
|
"categoryName16": { "message": "Verificare Captcha" },
|
||||||
|
"categoryName17": { "message": "Script pentru fonturi" },
|
||||||
|
"categoryName18": { "message": "Framework Web" },
|
||||||
|
"categoryName19": { "message": "Divers" },
|
||||||
|
"categoryName20": { "message": "Editor" },
|
||||||
|
"categoryName21": { "message": "LMS" },
|
||||||
|
"categoryName22": { "message": "Server Web" },
|
||||||
|
"categoryName23": { "message": "Unealtă Cache" },
|
||||||
|
"categoryName24": { "message": "Editor Texte Rich" },
|
||||||
|
"categoryName25": { "message": "Grafică JavaScript" },
|
||||||
|
"categoryName26": { "message": "Framework Mobile" },
|
||||||
|
"categoryName27": { "message": "Limbaj de programare" },
|
||||||
|
"categoryName28": { "message": "Sistem de operare" },
|
||||||
|
"categoryName29": { "message": "Motor de căutare" },
|
||||||
|
"categoryName30": { "message": "Poștă electronică" },
|
||||||
|
"categoryName31": { "message": "CDN" },
|
||||||
|
"categoryName32": { "message": "Automatizare marketing" },
|
||||||
|
"categoryName33": { "message": "Extensie server web" },
|
||||||
|
"categoryName34": { "message": "Bază de date" },
|
||||||
|
"categoryName35": { "message": "Hartă" },
|
||||||
|
"categoryName36": { "message": "Rețea de advertising" },
|
||||||
|
"categoryName37": { "message": "Serviciu rețea" },
|
||||||
|
"categoryName38": { "message": "Server Media" },
|
||||||
|
"categoryName39": { "message": "Webcam" },
|
||||||
|
"categoryName40": { "message": "Imprimantă" },
|
||||||
|
"categoryName41": { "message": "Sistem de plată" },
|
||||||
|
"categoryName42": { "message": "Manager cuvinte cheie" },
|
||||||
|
"categoryName43": { "message": "Paywall" },
|
||||||
|
"categoryName44": { "message": "Build/CI System" },
|
||||||
|
"categoryName45": { "message": "SCADA System" },
|
||||||
|
"categoryName46": { "message": "Remote Access" },
|
||||||
|
"categoryName47": { "message": "Development Tool" },
|
||||||
|
"categoryName48": { "message": "Network Storage" },
|
||||||
|
"categoryName49": { "message": "Feed Readers" },
|
||||||
|
"categoryName50": { "message": "Document Management Systems" },
|
||||||
|
"categoryName51": { "message": "Landing Page Builder" },
|
||||||
|
"categoryName52": { "message": "Live Chat" }
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<script src="js/browser-polyfill.js"></script>
|
||||||
|
<script src="js/wappalyzer.js"></script>
|
||||||
|
<script src="js/defaults.js"></script>
|
||||||
|
<script src="js/driver.js"></script>
|
||||||
|
<script src="js/network.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,106 @@
|
|||||||
|
body {
|
||||||
|
color: #303942;
|
||||||
|
cursor: default;
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
font-size: .8rem;
|
||||||
|
line-height: 1.4rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
border-bottom: 1px solid #dbdbdb;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0 0 1.5rem 0;
|
||||||
|
padding: 1rem 0 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.3em;
|
||||||
|
margin-bottom: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
color: black;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: rgb(17, 85, 204);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #4608ad;
|
||||||
|
border: none;
|
||||||
|
border-radius: .2rem;
|
||||||
|
color: white;
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 0 .6rem;
|
||||||
|
line-height: 1.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:active {
|
||||||
|
color: rgb(5, 37, 119);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
background: linear-gradient(160deg, #32067c, #150233);
|
||||||
|
padding: 1.5rem 0 1rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero img {
|
||||||
|
height: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#options-saved {
|
||||||
|
display: none;
|
||||||
|
margin-left: .5rem;
|
||||||
|
-webkit-animation: fadeout 2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about {
|
||||||
|
border-top: 1px solid #dbdbdb;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
padding: 1.5rem 0 1.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about img {
|
||||||
|
margin-right: .2rem;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#about button {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #dbdbdb;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #303942;
|
||||||
|
margin: 0 1rem .5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes fadeout {
|
||||||
|
from { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
body {
|
||||||
|
background: #fff;
|
||||||
|
color: #4a4a4a;
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 16px;
|
||||||
|
margin: 0;
|
||||||
|
min-width: 200px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #4a4a4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:focus {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: inline-block;
|
||||||
|
height: 16px;
|
||||||
|
margin-right: 8px;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app {
|
||||||
|
padding: 7px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app:last-child {
|
||||||
|
border: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app a {
|
||||||
|
color: #4608ad;
|
||||||
|
display: block;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app a .label .name {
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app a:hover .label .name {
|
||||||
|
border-bottom: 1px solid #4608ad;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app a .category .name {
|
||||||
|
color: #4a4a4a;
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detected-app a:hover .category .name {
|
||||||
|
border-bottom: 1px solid #4a4a4a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category {
|
||||||
|
display: block;
|
||||||
|
margin: 5px 0 0 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
color: #999;
|
||||||
|
font-style: italic;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
margin-top: 17px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer a:hover {
|
||||||
|
border-bottom: 1px solid #dbdbdb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#options {
|
||||||
|
float: right;
|
||||||
|
}
|
After Width: | Height: | Size: 281 B |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 555 B |
After Width: | Height: | Size: 643 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 373 B |
@ -0,0 +1,851 @@
|
|||||||
|
/* webextension-polyfill - v0.1.0 - Sat Mar 11 2017 11:35:13 */
|
||||||
|
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||||
|
/* vim: set sts=2 sw=2 et tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
if (typeof browser === "undefined") {
|
||||||
|
// Wrapping the bulk of this polyfill in a one-time-use function is a minor
|
||||||
|
// optimization for Firefox. Since Spidermonkey does not fully parse the
|
||||||
|
// contents of a function until the first time it's called, and since it will
|
||||||
|
// never actually need to be called, this allows the polyfill to be included
|
||||||
|
// in Firefox nearly for free.
|
||||||
|
const wrapAPIs = () => {
|
||||||
|
const apiMetadata = {
|
||||||
|
"alarms": {
|
||||||
|
"clear": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"clearAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bookmarks": {
|
||||||
|
"create": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"export": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getChildren": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getRecent": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getTree": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"getSubTree": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"import": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"move": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"removeTree": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"browserAction": {
|
||||||
|
"getBadgeBackgroundColor": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getBadgeText": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getPopup": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getTitle": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"setIcon": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commands": {
|
||||||
|
"getAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"contextMenus": {
|
||||||
|
"update": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"removeAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cookies": {
|
||||||
|
"get": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getAll": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getAllCookieStores": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"set": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"downloads": {
|
||||||
|
"download": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"cancel": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"erase": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getFileIcon": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"open": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"pause": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"removeFile": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"resume": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"show": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extension": {
|
||||||
|
"isAllowedFileSchemeAccess": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"isAllowedIncognitoAccess": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"history": {
|
||||||
|
"addUrl": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getVisits": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"deleteAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"deleteRange": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"deleteUrl": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"i18n": {
|
||||||
|
"detectLanguage": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getAcceptLanguages": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idle": {
|
||||||
|
"queryState": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"management": {
|
||||||
|
"get": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"getSelf": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"uninstallSelf": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"clear": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"create": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"getAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"getPermissionLevel": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pageAction": {
|
||||||
|
"getPopup": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getTitle": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"hide": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"setIcon": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"show": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"getBackgroundPage": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"getBrowserInfo": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"getPlatformInfo": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"openOptionsPage": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"requestUpdateCheck": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"sendMessage": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 3
|
||||||
|
},
|
||||||
|
"sendNativeMessage": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"setUninstallURL": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"local": {
|
||||||
|
"clear": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getBytesInUse": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"set": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"managed": {
|
||||||
|
"get": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getBytesInUse": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sync": {
|
||||||
|
"clear": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getBytesInUse": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"set": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tabs": {
|
||||||
|
"create": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"captureVisibleTab": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"detectLanguage": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"duplicate": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"executeScript": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getCurrent": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
},
|
||||||
|
"getZoom": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getZoomSettings": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"highlight": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"insertCSS": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"move": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"reload": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"query": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"removeCSS": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"sendMessage": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 3
|
||||||
|
},
|
||||||
|
"setZoom": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"setZoomSettings": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webNavigation": {
|
||||||
|
"getAllFrames": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getFrame": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"webRequest": {
|
||||||
|
"handlerBehaviorChanged": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"windows": {
|
||||||
|
"create": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"get": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 2
|
||||||
|
},
|
||||||
|
"getAll": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getCurrent": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"getLastFocused": {
|
||||||
|
"minArgs": 0,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"remove": {
|
||||||
|
"minArgs": 1,
|
||||||
|
"maxArgs": 1
|
||||||
|
},
|
||||||
|
"update": {
|
||||||
|
"minArgs": 2,
|
||||||
|
"maxArgs": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WeakMap subclass which creates and stores a value for any key which does
|
||||||
|
* not exist when accessed, but behaves exactly as an ordinary WeakMap
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @param {function} createItem
|
||||||
|
* A function which will be called in order to create the value for any
|
||||||
|
* key which does not exist, the first time it is accessed. The
|
||||||
|
* function receives, as its only argument, the key being created.
|
||||||
|
*/
|
||||||
|
class DefaultWeakMap extends WeakMap {
|
||||||
|
constructor(createItem, items = undefined) {
|
||||||
|
super(items);
|
||||||
|
this.createItem = createItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key) {
|
||||||
|
if (!this.has(key)) {
|
||||||
|
this.set(key, this.createItem(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.get(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the given object is an object with a `then` method, and can
|
||||||
|
* therefore be assumed to behave as a Promise.
|
||||||
|
*
|
||||||
|
* @param {*} value The value to test.
|
||||||
|
* @returns {boolean} True if the value is thenable.
|
||||||
|
*/
|
||||||
|
const isThenable = value => {
|
||||||
|
return value && typeof value === "object" && typeof value.then === "function";
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a function which, when called, will resolve or reject
|
||||||
|
* the given promise based on how it is called:
|
||||||
|
*
|
||||||
|
* - If, when called, `chrome.runtime.lastError` contains a non-null object,
|
||||||
|
* the promise is rejected with that value.
|
||||||
|
* - If the function is called with exactly one argument, the promise is
|
||||||
|
* resolved to that value.
|
||||||
|
* - Otherwise, the promise is resolved to an array containing all of the
|
||||||
|
* function's arguments.
|
||||||
|
*
|
||||||
|
* @param {object} promise
|
||||||
|
* An object containing the resolution and rejection functions of a
|
||||||
|
* promise.
|
||||||
|
* @param {function} promise.resolve
|
||||||
|
* The promise's resolution function.
|
||||||
|
* @param {function} promise.rejection
|
||||||
|
* The promise's rejection function.
|
||||||
|
*
|
||||||
|
* @returns {function}
|
||||||
|
* The generated callback function.
|
||||||
|
*/
|
||||||
|
const makeCallback = promise => {
|
||||||
|
return (...callbackArgs) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
promise.reject(chrome.runtime.lastError);
|
||||||
|
} else if (callbackArgs.length === 1) {
|
||||||
|
promise.resolve(callbackArgs[0]);
|
||||||
|
} else {
|
||||||
|
promise.resolve(callbackArgs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a wrapper function for a method with the given name and metadata.
|
||||||
|
*
|
||||||
|
* @param {string} name
|
||||||
|
* The name of the method which is being wrapped.
|
||||||
|
* @param {object} metadata
|
||||||
|
* Metadata about the method being wrapped.
|
||||||
|
* @param {integer} metadata.minArgs
|
||||||
|
* The minimum number of arguments which must be passed to the
|
||||||
|
* function. If called with fewer than this number of arguments, the
|
||||||
|
* wrapper will raise an exception.
|
||||||
|
* @param {integer} metadata.maxArgs
|
||||||
|
* The maximum number of arguments which may be passed to the
|
||||||
|
* function. If called with more than this number of arguments, the
|
||||||
|
* wrapper will raise an exception.
|
||||||
|
*
|
||||||
|
* @returns {function(object, ...*)}
|
||||||
|
* The generated wrapper function.
|
||||||
|
*/
|
||||||
|
const wrapAsyncFunction = (name, metadata) => {
|
||||||
|
const pluralizeArguments = (numArgs) => numArgs == 1 ? "argument" : "arguments";
|
||||||
|
|
||||||
|
return function asyncFunctionWrapper(target, ...args) {
|
||||||
|
if (args.length < metadata.minArgs) {
|
||||||
|
throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.length > metadata.maxArgs) {
|
||||||
|
throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
target[name](...args, makeCallback({resolve, reject}));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps an existing method of the target object, so that calls to it are
|
||||||
|
* intercepted by the given wrapper function. The wrapper function receives,
|
||||||
|
* as its first argument, the original `target` object, followed by each of
|
||||||
|
* the arguments passed to the orginal method.
|
||||||
|
*
|
||||||
|
* @param {object} target
|
||||||
|
* The original target object that the wrapped method belongs to.
|
||||||
|
* @param {function} method
|
||||||
|
* The method being wrapped. This is used as the target of the Proxy
|
||||||
|
* object which is created to wrap the method.
|
||||||
|
* @param {function} wrapper
|
||||||
|
* The wrapper function which is called in place of a direct invocation
|
||||||
|
* of the wrapped method.
|
||||||
|
*
|
||||||
|
* @returns {Proxy<function>}
|
||||||
|
* A Proxy object for the given method, which invokes the given wrapper
|
||||||
|
* method in its place.
|
||||||
|
*/
|
||||||
|
const wrapMethod = (target, method, wrapper) => {
|
||||||
|
return new Proxy(method, {
|
||||||
|
apply(targetMethod, thisObj, args) {
|
||||||
|
return wrapper.call(thisObj, target, ...args);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps an object in a Proxy which intercepts and wraps certain methods
|
||||||
|
* based on the given `wrappers` and `metadata` objects.
|
||||||
|
*
|
||||||
|
* @param {object} target
|
||||||
|
* The target object to wrap.
|
||||||
|
*
|
||||||
|
* @param {object} [wrappers = {}]
|
||||||
|
* An object tree containing wrapper functions for special cases. Any
|
||||||
|
* function present in this object tree is called in place of the
|
||||||
|
* method in the same location in the `target` object tree. These
|
||||||
|
* wrapper methods are invoked as described in {@see wrapMethod}.
|
||||||
|
*
|
||||||
|
* @param {object} [metadata = {}]
|
||||||
|
* An object tree containing metadata used to automatically generate
|
||||||
|
* Promise-based wrapper functions for asynchronous. Any function in
|
||||||
|
* the `target` object tree which has a corresponding metadata object
|
||||||
|
* in the same location in the `metadata` tree is replaced with an
|
||||||
|
* automatically-generated wrapper function, as described in
|
||||||
|
* {@see wrapAsyncFunction}
|
||||||
|
*
|
||||||
|
* @returns {Proxy<object>}
|
||||||
|
*/
|
||||||
|
const wrapObject = (target, wrappers = {}, metadata = {}) => {
|
||||||
|
let cache = Object.create(null);
|
||||||
|
|
||||||
|
let handlers = {
|
||||||
|
has(target, prop) {
|
||||||
|
return prop in target || prop in cache;
|
||||||
|
},
|
||||||
|
|
||||||
|
get(target, prop, receiver) {
|
||||||
|
if (prop in cache) {
|
||||||
|
return cache[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(prop in target)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = target[prop];
|
||||||
|
|
||||||
|
if (typeof value === "function") {
|
||||||
|
// This is a method on the underlying object. Check if we need to do
|
||||||
|
// any wrapping.
|
||||||
|
|
||||||
|
if (typeof wrappers[prop] === "function") {
|
||||||
|
// We have a special-case wrapper for this method.
|
||||||
|
value = wrapMethod(target, target[prop], wrappers[prop]);
|
||||||
|
} else if (hasOwnProperty(metadata, prop)) {
|
||||||
|
// This is an async method that we have metadata for. Create a
|
||||||
|
// Promise wrapper for it.
|
||||||
|
let wrapper = wrapAsyncFunction(prop, metadata[prop]);
|
||||||
|
value = wrapMethod(target, target[prop], wrapper);
|
||||||
|
} else {
|
||||||
|
// This is a method that we don't know or care about. Return the
|
||||||
|
// original method, bound to the underlying object.
|
||||||
|
value = value.bind(target);
|
||||||
|
}
|
||||||
|
} else if (typeof value === "object" && value !== null &&
|
||||||
|
(hasOwnProperty(wrappers, prop) ||
|
||||||
|
hasOwnProperty(metadata, prop))) {
|
||||||
|
// This is an object that we need to do some wrapping for the children
|
||||||
|
// of. Create a sub-object wrapper for it with the appropriate child
|
||||||
|
// metadata.
|
||||||
|
value = wrapObject(value, wrappers[prop], metadata[prop]);
|
||||||
|
} else {
|
||||||
|
// We don't need to do any wrapping for this property,
|
||||||
|
// so just forward all access to the underlying object.
|
||||||
|
Object.defineProperty(cache, prop, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return target[prop];
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
target[prop] = value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache[prop] = value;
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
|
||||||
|
set(target, prop, value, receiver) {
|
||||||
|
if (prop in cache) {
|
||||||
|
cache[prop] = value;
|
||||||
|
} else {
|
||||||
|
target[prop] = value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
defineProperty(target, prop, desc) {
|
||||||
|
return Reflect.defineProperty(cache, prop, desc);
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteProperty(target, prop) {
|
||||||
|
return Reflect.deleteProperty(cache, prop);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Proxy(target, handlers);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a set of wrapper functions for an event object, which handles
|
||||||
|
* wrapping of listener functions that those messages are passed.
|
||||||
|
*
|
||||||
|
* A single wrapper is created for each listener function, and stored in a
|
||||||
|
* map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`
|
||||||
|
* retrieve the original wrapper, so that attempts to remove a
|
||||||
|
* previously-added listener work as expected.
|
||||||
|
*
|
||||||
|
* @param {DefaultWeakMap<function, function>} wrapperMap
|
||||||
|
* A DefaultWeakMap object which will create the appropriate wrapper
|
||||||
|
* for a given listener function when one does not exist, and retrieve
|
||||||
|
* an existing one when it does.
|
||||||
|
*
|
||||||
|
* @returns {object}
|
||||||
|
*/
|
||||||
|
const wrapEvent = wrapperMap => ({
|
||||||
|
addListener(target, listener, ...args) {
|
||||||
|
target.addListener(wrapperMap.get(listener), ...args);
|
||||||
|
},
|
||||||
|
|
||||||
|
hasListener(target, listener) {
|
||||||
|
return target.hasListener(wrapperMap.get(listener));
|
||||||
|
},
|
||||||
|
|
||||||
|
removeListener(target, listener) {
|
||||||
|
target.removeListener(wrapperMap.get(listener));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onMessageWrappers = new DefaultWeakMap(listener => {
|
||||||
|
if (typeof listener !== "function") {
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a message listener function so that it may send responses based on
|
||||||
|
* its return value, rather than by returning a sentinel value and calling a
|
||||||
|
* callback. If the listener function returns a Promise, the response is
|
||||||
|
* sent when the promise either resolves or rejects.
|
||||||
|
*
|
||||||
|
* @param {*} message
|
||||||
|
* The message sent by the other end of the channel.
|
||||||
|
* @param {object} sender
|
||||||
|
* Details about the sender of the message.
|
||||||
|
* @param {function(*)} sendResponse
|
||||||
|
* A callback which, when called with an arbitrary argument, sends
|
||||||
|
* that value as a response.
|
||||||
|
* @returns {boolean}
|
||||||
|
* True if the wrapped listener returned a Promise, which will later
|
||||||
|
* yield a response. False otherwise.
|
||||||
|
*/
|
||||||
|
return function onMessage(message, sender, sendResponse) {
|
||||||
|
let result = listener(message, sender);
|
||||||
|
|
||||||
|
if (isThenable(result)) {
|
||||||
|
result.then(sendResponse, error => {
|
||||||
|
console.error(error);
|
||||||
|
sendResponse(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (result !== undefined) {
|
||||||
|
sendResponse(result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const staticWrappers = {
|
||||||
|
runtime: {
|
||||||
|
onMessage: wrapEvent(onMessageWrappers),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return wrapObject(chrome, staticWrappers, apiMetadata);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.browser = wrapAPIs();
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
(function() {
|
||||||
|
var c = {
|
||||||
|
init: function() {
|
||||||
|
var html = document.documentElement.outerHTML;
|
||||||
|
|
||||||
|
c.log('init');
|
||||||
|
|
||||||
|
if ( html.length > 50000 ) {
|
||||||
|
html = html.substring(0, 25000) + html.substring(html.length - 25000, html.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.runtime.sendMessage({ id: 'analyze', subject: { html: html } });
|
||||||
|
|
||||||
|
c.getEnvironmentVars();
|
||||||
|
},
|
||||||
|
|
||||||
|
log: function(message) {
|
||||||
|
browser.runtime.sendMessage({ id: 'log', message: '[ content.js ] ' + message });
|
||||||
|
},
|
||||||
|
|
||||||
|
getEnvironmentVars: function() {
|
||||||
|
var container, script;
|
||||||
|
|
||||||
|
c.log('getEnvironmentVars');
|
||||||
|
|
||||||
|
if ( typeof document.documentElement.innerHTML === 'undefined' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
container = document.createElement('wappalyzerData');
|
||||||
|
|
||||||
|
container.setAttribute('id', 'wappalyzerData');
|
||||||
|
container.setAttribute('style', 'display: none');
|
||||||
|
|
||||||
|
script = document.createElement('script');
|
||||||
|
|
||||||
|
script.setAttribute('id', 'wappalyzerEnvDetection');
|
||||||
|
script.setAttribute('src', browser.extension.getURL('js/inject.js'));
|
||||||
|
|
||||||
|
container.addEventListener('wappalyzerEvent', (function(event) {
|
||||||
|
var environmentVars = event.target.childNodes[0].nodeValue;
|
||||||
|
|
||||||
|
document.documentElement.removeChild(container);
|
||||||
|
document.documentElement.removeChild(script);
|
||||||
|
|
||||||
|
environmentVars = environmentVars.split(' ').slice(0, 500);
|
||||||
|
|
||||||
|
browser.runtime.sendMessage({ id: 'analyze', subject: { env: environmentVars } });
|
||||||
|
}), true);
|
||||||
|
|
||||||
|
document.documentElement.appendChild(container);
|
||||||
|
document.documentElement.appendChild(script);
|
||||||
|
} catch(e) {
|
||||||
|
c.log('Error: ' + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.init();
|
||||||
|
}());
|
@ -0,0 +1,5 @@
|
|||||||
|
var defaults = {
|
||||||
|
autoAnalyzeHeaders: 0,
|
||||||
|
upgradeMessage: 1,
|
||||||
|
tracking: 1
|
||||||
|
};
|
@ -0,0 +1,306 @@
|
|||||||
|
/**
|
||||||
|
* Chrome driver
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
if ( wappalyzer == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var w = wappalyzer,
|
||||||
|
firstRun = false,
|
||||||
|
upgraded = false,
|
||||||
|
tab,
|
||||||
|
tabCache = {},
|
||||||
|
headersCache = {};
|
||||||
|
|
||||||
|
w.driver = {
|
||||||
|
timeout: 1000,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log messages to console
|
||||||
|
*/
|
||||||
|
log: function(args) {
|
||||||
|
console.log('[wappalyzer ' + args.type + '] ' + args.message);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize
|
||||||
|
*/
|
||||||
|
init: function() {
|
||||||
|
w.log('init');
|
||||||
|
|
||||||
|
// Load apps.json
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.open('GET', 'apps.json', true);
|
||||||
|
|
||||||
|
xhr.overrideMimeType('application/json');
|
||||||
|
|
||||||
|
xhr.onload = function() {
|
||||||
|
var json = JSON.parse(xhr.responseText);
|
||||||
|
|
||||||
|
w.categories = json.categories;
|
||||||
|
w.apps = json.apps;
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(null);
|
||||||
|
|
||||||
|
// Version check
|
||||||
|
try {
|
||||||
|
var version = browser.app.getDetails().version;
|
||||||
|
|
||||||
|
if ( localStorage['version'] == null ) {
|
||||||
|
firstRun = true;
|
||||||
|
|
||||||
|
// Set defaults
|
||||||
|
for ( option in defaults ) {
|
||||||
|
localStorage[option] = defaults[option];
|
||||||
|
}
|
||||||
|
} else if ( version !== localStorage['version'] && parseInt(localStorage['upgradeMessage'], 10) ) {
|
||||||
|
upgraded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage['version'] = version;
|
||||||
|
} catch(e) { }
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
||||||
|
var
|
||||||
|
hostname,
|
||||||
|
a = document.createElement('a');
|
||||||
|
|
||||||
|
if ( typeof message.id != 'undefined' ) {
|
||||||
|
w.log('message: ' + message.id);
|
||||||
|
|
||||||
|
switch ( message.id ) {
|
||||||
|
case 'log':
|
||||||
|
w.log(message.message);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'analyze':
|
||||||
|
tab = sender.tab;
|
||||||
|
|
||||||
|
a.href = tab.url.replace(/#.*$/, '');
|
||||||
|
|
||||||
|
hostname = a.hostname;
|
||||||
|
|
||||||
|
if ( headersCache[a.href] !== undefined ) {
|
||||||
|
message.subject.headers = headersCache[a.href];
|
||||||
|
}
|
||||||
|
|
||||||
|
w.analyze(hostname, a.href, message.subject);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'ad_log':
|
||||||
|
w.adCache.push(message.subject);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'get_apps':
|
||||||
|
sendResponse({
|
||||||
|
tabCache: tabCache[message.tab.id],
|
||||||
|
apps: w.apps,
|
||||||
|
categories: w.categories
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.tabs.query({}).then(function(tabs) {
|
||||||
|
tabs.forEach(function(tab) {
|
||||||
|
if ( tab.url.match(/^https?:\/\//) ) {
|
||||||
|
browser.tabs.executeScript(tab.id, { file: 'js/content.js' });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.tabs.onRemoved.addListener(function(tabId) {
|
||||||
|
w.log('remove tab');
|
||||||
|
|
||||||
|
tabCache[tabId] = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Live intercept headers using webRequest API
|
||||||
|
browser.webRequest.onCompleted.addListener(function(details) {
|
||||||
|
var responseHeaders = {};
|
||||||
|
|
||||||
|
if ( details.responseHeaders ) {
|
||||||
|
var uri = details.url.replace(/#.*$/, ''); // Remove hash
|
||||||
|
|
||||||
|
details.responseHeaders.forEach(function(header) {
|
||||||
|
responseHeaders[header.name.toLowerCase()] = header.value || '' + header.binaryValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( headersCache.length > 50 ) {
|
||||||
|
headersCache = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( /text\/html/.test(responseHeaders['content-type']) ) {
|
||||||
|
if ( headersCache[uri] === undefined ) {
|
||||||
|
headersCache[uri] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( var header in responseHeaders ) {
|
||||||
|
headersCache[uri][header] = responseHeaders[header];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.log(JSON.stringify({ uri: uri, headers: responseHeaders }));
|
||||||
|
}
|
||||||
|
}, { urls: [ 'http://*/*', 'https://*/*' ], types: [ 'main_frame' ] }, [ 'responseHeaders' ]);
|
||||||
|
|
||||||
|
if ( firstRun ) {
|
||||||
|
w.driver.goToURL({ url: w.config.websiteURL + 'installed', medium: 'install' });
|
||||||
|
|
||||||
|
firstRun = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( upgraded ) {
|
||||||
|
w.driver.goToURL({ url: w.config.websiteURL + 'upgraded', medium: 'upgrade', background: true });
|
||||||
|
|
||||||
|
upgraded = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
goToURL: function(args) {
|
||||||
|
var url = args.url + ( typeof args.medium === 'undefined' ? '' : '?pk_campaign=chrome&pk_kwd=' + args.medium);
|
||||||
|
|
||||||
|
browser.tabs.create({ url: url, active: args.background === undefined || !args.background });
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display apps
|
||||||
|
*/
|
||||||
|
displayApps: function() {
|
||||||
|
var
|
||||||
|
url = tab.url.replace(/#.*$/, ''),
|
||||||
|
count = w.detected[url] ? Object.keys(w.detected[url]).length.toString() : '0';
|
||||||
|
|
||||||
|
if ( tabCache[tab.id] == null ) {
|
||||||
|
tabCache[tab.id] = {
|
||||||
|
count: 0,
|
||||||
|
appsDetected: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
tabCache[tab.id].count = count;
|
||||||
|
tabCache[tab.id].appsDetected = w.detected[url];
|
||||||
|
|
||||||
|
if ( count > 0 ) {
|
||||||
|
// Find the main application to display
|
||||||
|
var i, appName, found = false;
|
||||||
|
|
||||||
|
w.driver.categoryOrder.forEach(function(match) {
|
||||||
|
for ( appName in w.detected[url] ) {
|
||||||
|
w.apps[appName].cats.forEach(function(cat) {
|
||||||
|
var icon = w.apps[appName].icon;
|
||||||
|
|
||||||
|
if ( cat == match && !found ) {
|
||||||
|
if ( /\.svg$/i.test(icon) ) {
|
||||||
|
icon = 'converted/' + icon + '.png';
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.pageAction.setIcon({ tabId: tab.id, path: 'images/icons/' + icon });
|
||||||
|
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if ( typeof chrome !== 'undefined' ) {
|
||||||
|
// Browser polyfill doesn't seem to work here
|
||||||
|
chrome.pageAction.show(tab.id);
|
||||||
|
} else {
|
||||||
|
browser.pageAction.show(tab.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anonymously track detected applications for research purposes
|
||||||
|
*/
|
||||||
|
ping: function() {
|
||||||
|
if ( Object.keys(w.ping.hostnames).length && parseInt(localStorage['tracking'], 10) ) {
|
||||||
|
w.driver.post('http://ping.wappalyzer.com/v2/', w.ping);
|
||||||
|
|
||||||
|
w.log('w.driver.ping: ' + JSON.stringify(w.ping));
|
||||||
|
|
||||||
|
w.ping = { hostnames: {} };
|
||||||
|
|
||||||
|
w.driver.post('https://ad.wappalyzer.com/log/wp/', w.adCache);
|
||||||
|
|
||||||
|
w.adCache = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make POST request
|
||||||
|
*/
|
||||||
|
post: function(url, data) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
xhr.open('POST', url, true);
|
||||||
|
|
||||||
|
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function(e) {
|
||||||
|
if ( xhr.readyState == 4 ) {
|
||||||
|
w.log('w.driver.post: status ' + xhr.status + ' (' + url + ')');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send('json=' + encodeURIComponent(JSON.stringify(data)));
|
||||||
|
},
|
||||||
|
|
||||||
|
categoryOrder: [ // Used to pick the main application
|
||||||
|
1, // CMS
|
||||||
|
11, // Blog
|
||||||
|
6, // Web Shop
|
||||||
|
2, // Message Board
|
||||||
|
51, // Landing Page Builder
|
||||||
|
8, // Wiki
|
||||||
|
13, // Issue Tracker
|
||||||
|
30, // Web Mail
|
||||||
|
18, // Web Framework
|
||||||
|
21, // LMS
|
||||||
|
7, // Photo Gallery
|
||||||
|
38, // Media Server
|
||||||
|
3, // Database Manager
|
||||||
|
34, // Database
|
||||||
|
4, // Documentation Tool
|
||||||
|
9, // Hosting Panel
|
||||||
|
29, // Search Engine
|
||||||
|
12, // JavaScript Framework
|
||||||
|
26, // Mobile Framework
|
||||||
|
25, // JavaScript Graphics
|
||||||
|
22, // Web Server
|
||||||
|
27, // Programming Language
|
||||||
|
28, // Operating System
|
||||||
|
15, // Comment System
|
||||||
|
20, // Editor
|
||||||
|
41, // Payment Processor
|
||||||
|
10, // Analytics
|
||||||
|
32, // Marketing Automation
|
||||||
|
31, // CDN
|
||||||
|
23, // Cache Tool
|
||||||
|
17, // Font Script
|
||||||
|
24, // Rich Text Editor
|
||||||
|
35, // Map
|
||||||
|
5, // Widget
|
||||||
|
14, // Video Player
|
||||||
|
16, // Captcha
|
||||||
|
33, // Web Server Extension
|
||||||
|
37, // Network Device
|
||||||
|
39, // Webcam
|
||||||
|
40, // Printer
|
||||||
|
36, // Advertising Network
|
||||||
|
42, // Tag Managers
|
||||||
|
43, // Paywalls
|
||||||
|
19 // Miscellaneous
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
w.init();
|
||||||
|
}());
|
@ -0,0 +1,11 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var
|
||||||
|
i, value,
|
||||||
|
nodes = document.getElementsByTagName('*');
|
||||||
|
|
||||||
|
for ( i = 0; i < nodes.length; i ++ ) {
|
||||||
|
if ( attr = nodes[i].dataset.i18n ) {
|
||||||
|
nodes[i].innerHTML = browser.i18n.getMessage(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,14 @@
|
|||||||
|
(function() {
|
||||||
|
try {
|
||||||
|
var i, environmentVars, e = document.createEvent('Events');
|
||||||
|
|
||||||
|
e.initEvent('wappalyzerEvent', true, false);
|
||||||
|
|
||||||
|
for ( i in window ) {
|
||||||
|
environmentVars += i + ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('wappalyzerData').appendChild(document.createComment(environmentVars));
|
||||||
|
document.getElementById('wappalyzerData').dispatchEvent(e);
|
||||||
|
} catch(e) { }
|
||||||
|
}());
|
@ -0,0 +1,54 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var d = document;
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
opts: defaults,
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
options.load();
|
||||||
|
|
||||||
|
d.getElementById('github' ).addEventListener('click', function() { window.open(wappalyzer.config.githubURL); });
|
||||||
|
d.getElementById('twitter' ).addEventListener('click', function() { window.open(wappalyzer.config.twitterURL); });
|
||||||
|
d.getElementById('wappalyzer').addEventListener('click', function() { window.open(wappalyzer.config.websiteURL + '?pk_campaign=chrome&pk_kwd=options'); });
|
||||||
|
|
||||||
|
d.getElementById('options-save').addEventListener('click', options.save);
|
||||||
|
},
|
||||||
|
|
||||||
|
load: function() {
|
||||||
|
var option, value;
|
||||||
|
|
||||||
|
for ( option in options.opts ) {
|
||||||
|
if ( value = localStorage[option] ) {
|
||||||
|
options.opts[option] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( parseInt(options.opts.upgradeMessage) ) {
|
||||||
|
d.getElementById('option-upgrade-message').setAttribute('checked', 'checked');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( parseInt(options.opts.tracking) ) {
|
||||||
|
d.getElementById('option-tracking').setAttribute('checked', 'checked');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
save: function() {
|
||||||
|
var option;
|
||||||
|
|
||||||
|
options.opts.upgradeMessage = d.getElementById('option-upgrade-message').checked ? 1 : 0;
|
||||||
|
options.opts.tracking = d.getElementById('option-tracking' ).checked ? 1 : 0;
|
||||||
|
|
||||||
|
for ( option in options.opts ) {
|
||||||
|
localStorage[option] = options.opts[option];
|
||||||
|
}
|
||||||
|
|
||||||
|
d.getElementById('options-saved').style.display = 'inline';
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
d.getElementById('options-saved').style.display = 'none';
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
options.init();
|
||||||
|
});
|
@ -0,0 +1,68 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var
|
||||||
|
slugify, popup,
|
||||||
|
d = document,
|
||||||
|
detectedApps = d.getElementById('detected-apps');
|
||||||
|
|
||||||
|
slugify = function(string) {
|
||||||
|
return string.toLowerCase().replace(/ /g, '-').replace(/[^\w-]/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
popup = {
|
||||||
|
init: function() {
|
||||||
|
|
||||||
|
d.getElementById('options').addEventListener('click', function() {
|
||||||
|
window.open(browser.extension.getURL('options.html'));
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.tabs.query({ active: true }).then(function(tabs) {
|
||||||
|
if ( tabs[0].url.match(/https?:\/\//) ) {
|
||||||
|
detectedApps.innerHTML = '<div class="empty">' + browser.i18n.getMessage('noAppsDetected') + '</div>';
|
||||||
|
} else {
|
||||||
|
detectedApps.innerHTML = '<div class="empty">' + browser.i18n.getMessage('nothingToDo') + '</div>';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.displayApps();
|
||||||
|
},
|
||||||
|
|
||||||
|
displayApps: function() {
|
||||||
|
var appName, confidence, version;
|
||||||
|
|
||||||
|
browser.tabs.query({ active: true }).then(function(tabs) {
|
||||||
|
browser.runtime.sendMessage({ id: 'get_apps', tab: tabs[0] }, function(response) {
|
||||||
|
if ( response.tabCache && response.tabCache.count > 0 ) {
|
||||||
|
detectedApps.innerHTML = '';
|
||||||
|
|
||||||
|
for ( appName in response.tabCache.appsDetected ) {
|
||||||
|
confidence = response.tabCache.appsDetected[appName].confidenceTotal;
|
||||||
|
version = response.tabCache.appsDetected[appName].version;
|
||||||
|
|
||||||
|
html =
|
||||||
|
'<div class="detected-app">' +
|
||||||
|
'<a target="_blank" href="https://wappalyzer.com/applications/' + slugify(appName) + '">' +
|
||||||
|
'<img src="images/icons/' + response.apps[appName].icon + '"/>' +
|
||||||
|
'<span class="label"><span class="name">' + appName + '</span>' + ( version ? ' ' + version : '' ) + ( confidence < 100 ? ' (' + confidence + '% sure)' : '' ) + '</span>' +
|
||||||
|
'</a>';
|
||||||
|
|
||||||
|
response.apps[appName].cats.forEach(function(cat) {
|
||||||
|
html +=
|
||||||
|
'<a target="_blank" href="https://wappalyzer.com/categories/' + slugify(response.categories[cat]) + '">' +
|
||||||
|
'<span class="category"><span class="name">' + browser.i18n.getMessage('categoryName' + cat) + '</span></span>' +
|
||||||
|
'</a>';
|
||||||
|
});
|
||||||
|
|
||||||
|
html +=
|
||||||
|
'</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
detectedApps.innerHTML = detectedApps.innerHTML + html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
popup.init();
|
||||||
|
});
|
@ -0,0 +1,48 @@
|
|||||||
|
{ "name": "Wappalyzer",
|
||||||
|
"homepage_url": "https://wappalyzer.com/",
|
||||||
|
"description": "Identify web technologies",
|
||||||
|
"version": "3",
|
||||||
|
"default_locale": "en",
|
||||||
|
"manifest_version": 2,
|
||||||
|
"icons": {
|
||||||
|
"16": "images/icon_16.png",
|
||||||
|
"32": "images/icon_32.png",
|
||||||
|
"128": "images/icon_128.png"
|
||||||
|
},
|
||||||
|
"page_action": {
|
||||||
|
"default_icon": "images/icon_32.png",
|
||||||
|
"default_title": "Wappalyzer",
|
||||||
|
"default_popup": "popup.html"
|
||||||
|
},
|
||||||
|
"background": {
|
||||||
|
"page": "background.html"
|
||||||
|
},
|
||||||
|
"content_scripts": [ {
|
||||||
|
"matches": [ "http://*/*", "https://*/*" ],
|
||||||
|
"js": [
|
||||||
|
"js/browser-polyfill.js",
|
||||||
|
"js/content.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_idle"
|
||||||
|
}, {
|
||||||
|
"matches": [ "http://*/*", "https://*/*" ],
|
||||||
|
"js": [
|
||||||
|
"js/browser-polyfill.js",
|
||||||
|
"js/iframe.js"
|
||||||
|
],
|
||||||
|
"run_at": "document_start",
|
||||||
|
"all_frames": true
|
||||||
|
} ],
|
||||||
|
"web_accessible_resources": [
|
||||||
|
"js/inject.js"
|
||||||
|
],
|
||||||
|
"options_page": "options.html",
|
||||||
|
"permissions": [
|
||||||
|
"tabs",
|
||||||
|
"webRequest",
|
||||||
|
"webNavigation",
|
||||||
|
"http://*/*",
|
||||||
|
"https://*/*"
|
||||||
|
],
|
||||||
|
"content_security_policy": "script-src 'self'; object-src 'self'"
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title data-i18n="options">Wappalyzer options</title>
|
||||||
|
|
||||||
|
<link rel="icon" href="images/icon_16.png">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/options.css">
|
||||||
|
|
||||||
|
<script src="js/browser-polyfill.js"></script>
|
||||||
|
<script src="js/wappalyzer.js"></script>
|
||||||
|
<script src="js/defaults.js"></script>
|
||||||
|
<script src="js/options.js"></script>
|
||||||
|
<script src="js/i18n.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="hero">
|
||||||
|
<div class="container">
|
||||||
|
<img src="images/logo-white.svg">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div class="container">
|
||||||
|
<h1 data-i18n="options">Options</h1>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<label for="option-upgrade-message"><input id="option-upgrade-message" type="checkbox"> <span data-i18n="optionUpgradeMessage">Tell me about upgrades</span></label>
|
||||||
|
<label for="option-tracking"><input id="option-tracking" type="checkbox"> <span data-i18n="optionTracking">Anonymously send reports on detected applications to wappalyzer.com for research</span></label>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<button id="options-save" data-i18n="optionsSave">Save options</button> <span id="options-saved" data-i18n="optionsSaved">Saved</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div id="about">
|
||||||
|
<p>
|
||||||
|
<button id="github"><img src="images/github.png" width="16" height="16" alt=""/> <span data-i18n="github" >Fork Wappalyzer on GitHub!</span></button><!--
|
||||||
|
--><button id="twitter"><img src="images/twitter.png" width="16" height="16" alt=""/> <span data-i18n="twitter">Follow Wappalyzer on Twitter</span></button><!--
|
||||||
|
--><button id="wappalyzer"><img src="images/icon_16.png" width="16" height="16" alt=""/> <span data-i18n="website">Go to wappalyzer.com</span></button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="css/widgets.css">
|
||||||
|
<link rel="stylesheet" href="css/popup.css">
|
||||||
|
|
||||||
|
<script src="js/browser-polyfill.js"></script>
|
||||||
|
<script src="js/popup.js"></script>
|
||||||
|
<script src="js/i18n.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="detected-apps"></div>
|
||||||
|
|
||||||
|
<div id="footer">
|
||||||
|
<a href="javascript: void(0);" data-i18n="options" id="options">Options</a>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|