diff --git a/bin/wappalyzer-build b/bin/wappalyzer-build index 3f973b736..6a18d6bb6 100755 --- a/bin/wappalyzer-build +++ b/bin/wappalyzer-build @@ -66,6 +66,13 @@ pushd $WAPPALYZER_ROOT/src/drivers/chrome > /dev/null zip -qr $WAPPALYZER_ROOT/build/wappalyzer_chrome.zip . +# Google Chrome +echo "Building WebExtension driver..." + +pushd $WAPPALYZER_ROOT/src/drivers/webextension > /dev/null + +zip -qr $WAPPALYZER_ROOT/build/wappalyzer_webextension.zip . + popd > /dev/null echo "Done. Builds have been created in $WAPPALYZER_ROOT/build." diff --git a/bin/wappalyzer-links b/bin/wappalyzer-links index 25f589406..dbb52a483 100755 --- a/bin/wappalyzer-links +++ b/bin/wappalyzer-links @@ -46,6 +46,16 @@ if [ "$(compgen -G "$path/icons/converted/*.png" | head -n1)" ]; then ln -f $path/icons/converted/*.png $path/drivers/chrome/images/icons/converted fi +ln -f $path/wappalyzer.js $path/drivers/webextension/js +ln -f $path/apps.json $path/drivers/webextension +ln -f $path/icons/*.png $path/drivers/webextension/images/icons +ln -f $path/icons/*.svg $path/drivers/webextension/images/icons +ln -f $path/utils/*.js $path/drivers/webextension/js + +if [ "$(compgen -G "$path/icons/converted/*.png" | head -n1)" ]; then + ln -f $path/icons/converted/*.png $path/drivers/webextension/images/icons/converted +fi + echo "OK" exit 0 diff --git a/bin/wappalyzer-validate b/bin/wappalyzer-validate index d9d09a617..0106c4d18 100755 --- a/bin/wappalyzer-validate +++ b/bin/wappalyzer-validate @@ -1,23 +1,20 @@ #!/bin/bash -path=$1 +path="$1" -if [ -z $path ] -then - if [ -z $WAPPALYZER_ROOT ] - then +if [ -z "$path" ]; then + if [ -z "$WAPPALYZER_ROOT" ]; then echo "-$(basename $0): No path specified" exit 1 fi - path=$WAPPALYZER_ROOT + path="$WAPPALYZER_ROOT" fi set -eu -if [ ! -d $path/src ] -then +if [ ! -d "$path/src" ]; then echo "-$(basename $0): Incorrect path" exit 1 @@ -27,7 +24,7 @@ path="$path/src" echo "Validating apps.json..." -node $WAPPALYZER_NODE_PATH/node_modules/jsonlint/lib/cli.js --quiet -V $WAPPALYZER_ROOT/schema.json $path/apps.json +node "$WAPPALYZER_NODE_PATH/node_modules/jsonlint/lib/cli.js" --quiet -V "$WAPPALYZER_ROOT/schema.json" "$path/apps.json" echo "Validating regular expressions..." diff --git a/src/drivers/webextension/.gitignore b/src/drivers/webextension/.gitignore new file mode 100644 index 000000000..602df1590 --- /dev/null +++ b/src/drivers/webextension/.gitignore @@ -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 diff --git a/src/drivers/webextension/_locales/el/messages.json b/src/drivers/webextension/_locales/el/messages.json new file mode 100644 index 000000000..8b63568f5 --- /dev/null +++ b/src/drivers/webextension/_locales/el/messages.json @@ -0,0 +1,60 @@ +{ + "github": { "message": "Κάνε fork το Wappalyzer στο GitHub!" }, + "twitter": { "message": "Ακολούθησε το Wappalyzer στο Twitter" }, + "website": { "message": "Πήγαινε στο wappalyzer.com" }, + "options": { "message": "Ρυθμίσεις Wappalyzer" }, + "optionsSave": { "message": "Ρυθμίσεις αποθήκευσης" }, + "optionsSaved": { "message": "Αποθηκεύτηκε" }, + "optionUpgradeMessage": { "message": "Ενημερώστε με για αναβαθμίσεις" }, + "optionTracking": { "message": "Ανώνυμη αποστολή αναφορών για εντοπισμένες εφαρμογές στο wappalyzer.com για έρευνα" }, + "nothingToDo": { "message": "Καμία ενέργεια." }, + "noAppsDetected": { "message": "Δεν ανιχνεύθηκαν εφαρμογές." }, + "categoryName1": { "message": "CMS" }, + "categoryName2": { "message": "Διαδικτυακό Φόρουμ" }, + "categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" }, + "categoryName4": { "message": "Εργαλείο Τεκμηρίωσης" }, + "categoryName5": { "message": "Widget" }, + "categoryName10": { "message": "Analytics" }, + "categoryName11": { "message": "Blog" }, + "categoryName12": { "message": "Framework της JavaScript" }, + "categoryName13": { "message": "Issue Tracker" }, + "categoryName14": { "message": "Πρόγραμμα αναπαραγωγής Βίντεο" }, + "categoryName15": { "message": "Σύστημα Σχολίων" }, + "categoryName16": { "message": "Captcha" }, + "categoryName17": { "message": "Script Γραμματοσειράς" }, + "categoryName18": { "message": "Framework Διαδικτύου" }, + "categoryName19": { "message": "Διάφορα" }, + "categoryName20": { "message": "Επεξεργαστής Κειμένου" }, + "categoryName21": { "message": "LMS" }, + "categoryName22": { "message": "Διακομιστής Διαδικτύου" }, + "categoryName23": { "message": "Εργαλείο Μνήμης Cache" }, + "categoryName24": { "message": "Επεξεργαστής Εμπλουτισμένου Κειμένου" }, + "categoryName25": { "message": "Γραφικά JavaScript" }, + "categoryName26": { "message": "Framework για Κινητά" }, + "categoryName27": { "message": "Γλώσσα Προγραμματισμού" }, + "categoryName28": { "message": "Λειτουργικό Σύστημα" }, + "categoryName29": { "message": "Μηχανή Αναζήτησης" }, + "categoryName30": { "message": "Web Mail" }, + "categoryName31": { "message": "CDN" }, + "categoryName32": { "message": "Αυτοματοποίηση Marketing" }, + "categoryName33": { "message": "Επέκταση Διακομιστή Διαδικτύου" }, + "categoryName34": { "message": "Βάση Δεδομένων" }, + "categoryName35": { "message": "Χάρτης" }, + "categoryName36": { "message": "Δίκτυο Διαφημίσεων" }, + "categoryName37": { "message": "Υπηρεσία Δικτύου" }, + "categoryName38": { "message": "Διακομιστής Πολυμέσων" }, + "categoryName39": { "message": "Διαδικτυακή κάμερα" }, + "categoryName40": { "message": "Εκτυπωτής" }, + "categoryName41": { "message": "Σύστημα Επεξεργασίας Πληρωμών" }, + "categoryName42": { "message": "Σύστημα Διαχείρισης Tags" }, + "categoryName43": { "message": "Paywall" }, + "categoryName44": { "message": "Σύστημα Build/CI" }, + "categoryName45": { "message": "Σύστημα SCADA" }, + "categoryName46": { "message": "Απομακρυσμένη Πρόσβαση" }, + "categoryName47": { "message": "Εργαλείο Ανάπτυξης" }, + "categoryName48": { "message": "Δικτυακός Αποθηκευτικός Χώρος" }, + "categoryName49": { "message": "Feed Readers" }, + "categoryName50": { "message": "Συστήματα Διαχειρίσης Εγγράφων" }, + "categoryName51": { "message": "Σύστημα Κατασκευής Σελίδων Υποδοχής" }, + "categoryName52": { "message": "Live Chat" } +} diff --git a/src/drivers/webextension/_locales/en/messages.json b/src/drivers/webextension/_locales/en/messages.json new file mode 100644 index 000000000..ba2c15174 --- /dev/null +++ b/src/drivers/webextension/_locales/en/messages.json @@ -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" } +} diff --git a/src/drivers/webextension/_locales/es/messages.json b/src/drivers/webextension/_locales/es/messages.json new file mode 100644 index 000000000..666deb714 --- /dev/null +++ b/src/drivers/webextension/_locales/es/messages.json @@ -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" } +} diff --git a/src/drivers/webextension/_locales/fr/messages.json b/src/drivers/webextension/_locales/fr/messages.json new file mode 100644 index 000000000..743d79210 --- /dev/null +++ b/src/drivers/webextension/_locales/fr/messages.json @@ -0,0 +1,64 @@ +{ + "github": { "message": "Forker Wappalyzer sur GitHub!" }, + "noAppsDetected": { "message": "Pas d'applications détectées." }, + "nothingToDo": { "message": "Rien à faire ici." }, + "optionTracking": { "message": "Envoyer anonymement des rapports sur les applications détectées à wappalyzer.com pour la recherche" }, + "optionUpgradeMessage": { "message": "M'afficher les mises à jour" }, + "options": { "message": "Options" }, + "optionsSave": { "message": "Sauver les options" }, + "optionsSaved": { "message": "Sauvé" }, + "twitter": { "message": "Suivre Wappalyzer sur Twitter" }, + "website": { "message": "Aller à wappalyzer.com" }, + "categoryName1": { "message": "CMS" }, + "categoryName2": { "message": "Forum" }, + "categoryName3": { "message": "Gestionnaire de base de données" }, + "categoryName4": { "message": "Outil de documentation" }, + "categoryName5": { "message": "Widget" }, + "categoryName6": { "message": "Boutique en ligne" }, + "categoryName7": { "message": "Galerie photo" }, + "categoryName8": { "message": "Wiki" }, + "categoryName9": { "message": "Gestionnaires de serveur" }, + "categoryName10": { "message": "Outil de statistiques" }, + "categoryName11": { "message": "Blog" }, + "categoryName12": { "message": "Framework JavaScript" }, + "categoryName13": { "message": "Outil de suivi de problèmes" }, + "categoryName14": { "message": "Lecteur de vidéos" }, + "categoryName15": { "message": "Système de commentaires" }, + "categoryName16": { "message": "Captcha" }, + "categoryName17": { "message": "Script de police" }, + "categoryName18": { "message": "Framework web" }, + "categoryName19": { "message": "Divers" }, + "categoryName20": { "message": "Editeur" }, + "categoryName21": { "message": "LMS" }, + "categoryName22": { "message": "Serveur web" }, + "categoryName23": { "message": "Outil de cache" }, + "categoryName24": { "message": "Editeur WYSIWYG" }, + "categoryName25": { "message": "Graphismes JavaScript" }, + "categoryName26": { "message": "Framework pour mobiles" }, + "categoryName27": { "message": "Language de programmation" }, + "categoryName28": { "message": "Système d'exploitation" }, + "categoryName29": { "message": "Moteur de recherche" }, + "categoryName30": { "message": "Web Mail" }, + "categoryName31": { "message": "CDN" }, + "categoryName32": { "message": "Logiciel de marketing" }, + "categoryName33": { "message": "Extension de serveur web" }, + "categoryName34": { "message": "Base de données" }, + "categoryName35": { "message": "Carte" }, + "categoryName36": { "message": "Réseau publicitaire" }, + "categoryName37": { "message": "Périphérique réseau" }, + "categoryName38": { "message": "Serveur multimédia" }, + "categoryName39": { "message": "Webcam" }, + "categoryName40": { "message": "Imprimante" }, + "categoryName41": { "message": "Service de paiement" }, + "categoryName42": { "message": "Tag Manager" }, + "categoryName43": { "message": "Paywall" }, + "categoryName44": { "message": "Système CI" }, + "categoryName45": { "message": "Système SCADA" }, + "categoryName46": { "message": "Accès à distance" }, + "categoryName47": { "message": "Outil de développement" }, + "categoryName48": { "message": "Stockage réseau" }, + "categoryName49": { "message": "Lecteur RSS" }, + "categoryName50": { "message": "Système de gestion de documents" }, + "categoryName51": { "message": "Landing Page Builder" }, + "categoryName52": { "message": "Chat en direct" } +} diff --git a/src/drivers/webextension/_locales/gr/messages.json b/src/drivers/webextension/_locales/gr/messages.json new file mode 100644 index 000000000..f512dad8f --- /dev/null +++ b/src/drivers/webextension/_locales/gr/messages.json @@ -0,0 +1,60 @@ +{ + "github": { "message": "Κάνε fork το Wappalyzer στο GitHub!" }, + "twitter": { "message": "Ακολούθησε το Wappalyzer στο Twitter" }, + "website": { "message": "Πήγαινε στο wappalyzer.com" }, + "options": { "message": "Ρυθμίσεις" }, + "optionsSave": { "message": "Ρυθμίσεις αποθήκευσης" }, + "optionsSaved": { "message": "Αποθηκεύτηκε" }, + "optionUpgradeMessage": { "message": "Ενημερώστε με για αναβαθμίσεις" }, + "optionTracking": { "message": "Ανώνυμη αποστολή αναφορών για εντοπισμένες εφαρμογές στο wappalyzer.com για έρευνα" }, + "nothingToDo": { "message": "Καμία ενέργεια." }, + "noAppsDetected": { "message": "Δεν ανιχνεύθηκαν εφαρμογές." }, + "categoryName1": { "message": "CMS" }, + "categoryName2": { "message": "Διαδικτυακό Φόρουμ" }, + "categoryName3": { "message": "Διαχειριστής Βάσης Δεδομένων" }, + "categoryName4": { "message": "Εργαλείο Τεκμηρίωσης" }, + "categoryName5": { "message": "Widget" }, + "categoryName10": { "message": "Analytics" }, + "categoryName11": { "message": "Blog" }, + "categoryName12": { "message": "Framework της JavaScript" }, + "categoryName13": { "message": "Issue Tracker" }, + "categoryName14": { "message": "Πρόγραμμα αναπαραγωγής Βίντεο" }, + "categoryName15": { "message": "Σύστημα Σχολίων" }, + "categoryName16": { "message": "Captcha" }, + "categoryName17": { "message": "Script Γραμματοσειράς" }, + "categoryName18": { "message": "Framework Διαδικτύου" }, + "categoryName19": { "message": "Διάφορα" }, + "categoryName20": { "message": "Επεξεργαστής Κειμένου" }, + "categoryName21": { "message": "LMS" }, + "categoryName22": { "message": "Διακομιστής Διαδικτύου" }, + "categoryName23": { "message": "Εργαλείο Μνήμης Cache" }, + "categoryName24": { "message": "Επεξεργαστής Εμπλουτισμένου Κειμένου" }, + "categoryName25": { "message": "Γραφικά JavaScript" }, + "categoryName26": { "message": "Framework για Κινητά" }, + "categoryName27": { "message": "Γλώσσα Προγραμματισμού" }, + "categoryName28": { "message": "Λειτουργικό Σύστημα" }, + "categoryName29": { "message": "Μηχανή Αναζήτησης" }, + "categoryName30": { "message": "Web Mail" }, + "categoryName31": { "message": "CDN" }, + "categoryName32": { "message": "Αυτοματοποίηση Marketing" }, + "categoryName33": { "message": "Επέκταση Διακομιστή Διαδικτύου" }, + "categoryName34": { "message": "Βάση Δεδομένων" }, + "categoryName35": { "message": "Χάρτης" }, + "categoryName36": { "message": "Δίκτυο Διαφημίσεων" }, + "categoryName37": { "message": "Υπηρεσία Δικτύου" }, + "categoryName38": { "message": "Διακομιστής Πολυμέσων" }, + "categoryName39": { "message": "Διαδικτυακή κάμερα" }, + "categoryName40": { "message": "Εκτυπωτής" }, + "categoryName41": { "message": "Σύστημα Επεξεργασίας Πληρωμών" }, + "categoryName42": { "message": "Σύστημα Διαχείρισης Tags" }, + "categoryName43": { "message": "Paywall" }, + "categoryName44": { "message": "Σύστημα Build/CI" }, + "categoryName45": { "message": "Σύστημα SCADA" }, + "categoryName46": { "message": "Απομακρυσμένη Πρόσβαση" }, + "categoryName47": { "message": "Εργαλείο Ανάπτυξης" }, + "categoryName48": { "message": "Δικτυακός Αποθηκευτικός Χώρος" }, + "categoryName49": { "message": "Feed Readers" }, + "categoryName50": { "message": "Συστήματα Διαχειρίσης Εγγράφων" }, + "categoryName51": { "message": "Σύστημα Κατασκευής Σελίδων Υποδοχής" }, + "categoryName52": { "message": "Live Chat" } +} diff --git a/src/drivers/webextension/_locales/it/messages.json b/src/drivers/webextension/_locales/it/messages.json new file mode 100644 index 000000000..ede043b3b --- /dev/null +++ b/src/drivers/webextension/_locales/it/messages.json @@ -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" } +} + diff --git a/src/drivers/webextension/_locales/ro/messages.json b/src/drivers/webextension/_locales/ro/messages.json new file mode 100644 index 000000000..6d938bc67 --- /dev/null +++ b/src/drivers/webextension/_locales/ro/messages.json @@ -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" } +} diff --git a/src/drivers/webextension/_locales/ru/messages.json b/src/drivers/webextension/_locales/ru/messages.json new file mode 100644 index 000000000..4cf46ecbc --- /dev/null +++ b/src/drivers/webextension/_locales/ru/messages.json @@ -0,0 +1,60 @@ +{ + "categoryName1" : { "message" : "CMS" }, + "categoryName2" : { "message" : "Форум" }, + "categoryName3" : { "message" : "Менеджер БД" }, + "categoryName4" : { "message" : "Документация" }, + "categoryName5" : { "message" : "Виджет" }, + "categoryName10" : { "message" : "Аналитика" }, + "categoryName11" : { "message" : "Блог" }, + "categoryName12" : { "message" : "JS фреймворк" }, + "categoryName13" : { "message" : "Баг трекер" }, + "categoryName14" : { "message" : "Видео плеер" }, + "categoryName15" : { "message" : "Система комментариев" }, + "categoryName16" : { "message" : "Капча" }, + "categoryName17" : { "message" : "Шрифт" }, + "categoryName18" : { "message" : "Веб фреймворк" }, + "categoryName19" : { "message" : "Прочее" }, + "categoryName20" : { "message" : "HTML редактор" }, + "categoryName21" : { "message" : "LMS" }, + "categoryName22" : { "message" : "Веб сервер" }, + "categoryName23" : { "message" : "Кеширование" }, + "categoryName24" : { "message" : "WYSIWYG редактор" }, + "categoryName25" : { "message" : "JS графика" }, + "categoryName26" : { "message" : "Мобильный фреймворк" }, + "categoryName27" : { "message" : "Язык программирования" }, + "categoryName28" : { "message" : "Операционная система" }, + "categoryName29" : { "message" : "Поисковый движок" }, + "categoryName30" : { "message" : "Веб почта" }, + "categoryName31" : { "message" : "CDN" }, + "categoryName32" : { "message" : "Управление маркетингом" }, + "categoryName33" : { "message" : "Расширение Веб сервера" }, + "categoryName34" : { "message" : "База данных" }, + "categoryName35" : { "message" : "Карта" }, + "categoryName36" : { "message" : "Рекламная сеть" }, + "categoryName37" : { "message" : "Сетевая служба" }, + "categoryName38" : { "message" : "Медиа сервер" }, + "categoryName39" : { "message" : "Вебкамера" }, + "categoryName40" : { "message" : "Принтер" }, + "categoryName41" : { "message" : "Провайдер платежей" }, + "categoryName42" : { "message" : "Менеджер тэгов" }, + "categoryName43" : { "message" : "Paywall" }, + "categoryName44" : { "message" : "Система непрерывной интеграции" }, + "categoryName45" : { "message" : "Система SCADA" }, + "categoryName46" : { "message" : "Удаленное управление" }, + "categoryName47" : { "message" : "Утилита для разработчиков" }, + "categoryName48" : { "message" : "Сетевое хранилище" }, + "categoryName49" : { "message" : "Граббер контента" }, + "categoryName50" : { "message" : "Управление документами" }, + "categoryName51" : { "message": "Генератор лендингов" }, + "categoryName52" : { "message": "Live Chat" }, + "github" : { "message" : "Форкнуть на GitHub!" }, + "noAppsDetected" : { "message" : "Нет данных о сайте" }, + "nothingToDo" : { "message" : "Тут нечего искать" }, + "optionTracking" : { "message" : "Анонимно отправлять статистику распознанных данных на сервер (для улучшения расширения)" }, + "optionUpgradeMessage" : { "message" : "Оповещать меня о новых обновлениях" }, + "options" : { "message" : "Настройки" }, + "optionsSave" : { "message" : "Сохранить" }, + "optionsSaved" : { "message" : "Успешно сохранено!" }, + "twitter" : { "message" : "Следите за новостями в Твиттере" }, + "website" : { "message" : "Перейти на Wappalyzer.com" } +} diff --git a/src/drivers/webextension/background.html b/src/drivers/webextension/background.html new file mode 100644 index 000000000..06e298abf --- /dev/null +++ b/src/drivers/webextension/background.html @@ -0,0 +1,15 @@ + + + +
+ + + + + + + + + + + diff --git a/src/drivers/webextension/css/options.css b/src/drivers/webextension/css/options.css new file mode 100644 index 000000000..bd6096f5f --- /dev/null +++ b/src/drivers/webextension/css/options.css @@ -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; } +} diff --git a/src/drivers/webextension/css/popup.css b/src/drivers/webextension/css/popup.css new file mode 100644 index 000000000..6c91d5888 --- /dev/null +++ b/src/drivers/webextension/css/popup.css @@ -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; +} diff --git a/src/drivers/webextension/images/github.png b/src/drivers/webextension/images/github.png new file mode 100644 index 000000000..037d0c336 Binary files /dev/null and b/src/drivers/webextension/images/github.png differ diff --git a/src/drivers/webextension/images/icon_128.png b/src/drivers/webextension/images/icon_128.png new file mode 100644 index 000000000..05ad20d8f Binary files /dev/null and b/src/drivers/webextension/images/icon_128.png differ diff --git a/src/drivers/webextension/images/icon_16.png b/src/drivers/webextension/images/icon_16.png new file mode 100644 index 000000000..31e9b7c86 Binary files /dev/null and b/src/drivers/webextension/images/icon_16.png differ diff --git a/src/drivers/webextension/images/icon_19.png b/src/drivers/webextension/images/icon_19.png new file mode 100644 index 000000000..9668bc65a Binary files /dev/null and b/src/drivers/webextension/images/icon_19.png differ diff --git a/src/drivers/webextension/images/icon_32.png b/src/drivers/webextension/images/icon_32.png new file mode 100644 index 000000000..cc9d30b15 Binary files /dev/null and b/src/drivers/webextension/images/icon_32.png differ diff --git a/src/drivers/webextension/images/icon_38.png b/src/drivers/webextension/images/icon_38.png new file mode 100644 index 000000000..95f220ff3 Binary files /dev/null and b/src/drivers/webextension/images/icon_38.png differ diff --git a/src/drivers/webextension/images/icons/.gitkeep b/src/drivers/webextension/images/icons/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/drivers/webextension/images/icons/converted/.gitkeep b/src/drivers/webextension/images/icons/converted/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/drivers/webextension/images/logo-white.svg b/src/drivers/webextension/images/logo-white.svg new file mode 100644 index 000000000..bfbecc41b --- /dev/null +++ b/src/drivers/webextension/images/logo-white.svg @@ -0,0 +1,29 @@ + + \ No newline at end of file diff --git a/src/drivers/webextension/images/twitter.png b/src/drivers/webextension/images/twitter.png new file mode 100644 index 000000000..e20284ddf Binary files /dev/null and b/src/drivers/webextension/images/twitter.png differ diff --git a/src/drivers/webextension/js/browser-polyfill.js b/src/drivers/webextension/js/browser-polyfill.js new file mode 100644 index 000000000..76cb766e1 --- /dev/null +++ b/src/drivers/webextension/js/browser-polyfill.js @@ -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