From 9eebc95ab8320af215cdf5bea0dfd7e66a3e1718 Mon Sep 17 00:00:00 2001 From: Elbert Alias Date: Sun, 7 Oct 2012 12:34:42 +1100 Subject: [PATCH] Improved preferences screen --- drivers/chrome/js/driver.js | 2 +- drivers/firefox/content/js/content.js | 38 ++- drivers/firefox/content/js/driver.js | 66 ++--- drivers/firefox/content/xul/preferences.xul | 258 ++++++++---------- drivers/firefox/content/xul/wappalyzer.xul | 2 - .../firefox/defaults/preferences/defaults.js | 75 ++--- drivers/firefox/install.rdf | 8 +- drivers/firefox/locale/de-DE/wappalyzer.dtd | 94 +++---- drivers/firefox/locale/en-US/wappalyzer.dtd | 94 ++++--- drivers/firefox/locale/fr-FR/wappalyzer.dtd | 93 ++++--- drivers/firefox/locale/nl-NL/wappalyzer.dtd | 91 +++--- .../{icon.png => skin/images/icon128x128.png} | Bin drivers/firefox/skin/images/icon64x64.png | Bin 0 -> 5039 bytes 13 files changed, 411 insertions(+), 410 deletions(-) rename drivers/firefox/{icon.png => skin/images/icon128x128.png} (100%) create mode 100644 drivers/firefox/skin/images/icon64x64.png diff --git a/drivers/chrome/js/driver.js b/drivers/chrome/js/driver.js index 668489833..2c67b5c41 100644 --- a/drivers/chrome/js/driver.js +++ b/drivers/chrome/js/driver.js @@ -96,7 +96,7 @@ }, goToURL: function(args) { - window.open(args.url); + window.open(args.url + '?utm_source=firefox&utm_medium=extension&utm_campaign=extensions'); }, /** diff --git a/drivers/firefox/content/js/content.js b/drivers/firefox/content/js/content.js index 7f8bc44dc..60927bb97 100644 --- a/drivers/firefox/content/js/content.js +++ b/drivers/firefox/content/js/content.js @@ -1,28 +1,40 @@ "use strict"; (function() { - var lastEnv = null; + var + lastEnv = null, + prefs = {} + ; addEventListener('DOMContentLoaded', function() { removeEventListener('DOMContentLoaded', onLoad, false); + prefs = sendSyncMessage('wappalyzer', { action: 'get prefs' })[0]; + onLoad(); }, false); function onLoad() { if ( content.document.contentType != 'text/html' ) { return; } - content.document.documentElement.addEventListener('load', function() { - var env = Object.keys(content.wrappedJSObject); + if ( prefs.analyzeOnLoad ) { + content.document.documentElement.addEventListener('load', function() { + var env = Object.keys(content.wrappedJSObject); - if ( env.join() !== lastEnv ) { - lastEnv = env.join(); + if ( env.join() !== lastEnv ) { + lastEnv = env.join(); - sendAsyncMessage('wappalyzer', { env: Object.keys(content.wrappedJSObject) }); - } + sendAsyncMessage('wappalyzer', { + action: 'analyze', + analyze: { + env: Object.keys(content.wrappedJSObject) + } + }); + } - removeEventListener('load', onLoad, true); - }, true); + removeEventListener('load', onLoad, true); + }, true); + } // HTML var html = content.document.documentElement.outerHTML; @@ -37,9 +49,13 @@ } sendAsyncMessage('wappalyzer', { + action: 'analyze', hostname: content.location.hostname, - html: html, - url: content.location.href + url: content.location.href, + analyze: { + html: html, + env: prefs.analyzeJavaScript ? Object.keys(content.wrappedJSObject) : [] + } }); } })(); diff --git a/drivers/firefox/content/js/driver.js b/drivers/firefox/content/js/driver.js index 7df97e7cd..d67d232c9 100644 --- a/drivers/firefox/content/js/driver.js +++ b/drivers/firefox/content/js/driver.js @@ -39,13 +39,13 @@ AddonManager.getAddonByID('wappalyzer@crunchlabz.com', function(addon) { // Load jQuery - (function () { - Cc['@mozilla.org/moz/jssubscript-loader;1'].getService(Ci.mozIJSSubScriptLoader).loadSubScript('chrome://wappalyzer/content/js/lib/jquery.min.js'); - })(); + Cc['@mozilla.org/moz/jssubscript-loader;1'].getService(Ci.mozIJSSubScriptLoader).loadSubScript('chrome://wappalyzer/content/js/lib/jquery.min.js'); // Preferences prefs = Cc['@mozilla.org/preferences-service;1'].getService(Ci.nsIPrefService).getBranch('extensions.wappalyzer.'); + prefs.addObserver('', w.driver, false); + container(); bindings(); @@ -75,6 +75,8 @@ // Get response headers onStateChange: function(progress, request, flags, status) { + if ( !prefs.getBoolPref('analyzeHeaders') ) { return; } + if ( request != null && flags & Ci.nsIWebProgressListener.STATE_STOP ) { if ( request.nsIHttpChannel && request.contentType == 'text/html' ) { if ( progress.currentURI && request.name == progress.currentURI.spec ) { @@ -101,6 +103,20 @@ window.addEventListener('unload', w.driver.track, false); }, + // Observe preference changes + observe: function(subject, topic, data) { + if ( topic != 'nsPref:changed' ) { return; } + + switch(data) { + case 'addonBar': + container(); + + break; + } + + w.driver.displayApps(); + }, + /** * Display apps */ @@ -203,7 +219,7 @@ * Go to URL */ goToURL: function(args) { - gBrowser.selectedTab = gBrowser.addTab(args.url); + gBrowser.selectedTab = gBrowser.addTab(args.url + '?utm_source=firefox&utm_medium=extension&utm_campaign=extensions'); }, /** @@ -237,7 +253,19 @@ function content(msg) { w.log('content.js'); - w.analyze(msg.json.hostname, msg.json.url, { html: msg.json.html, env: msg.json.env }); + switch ( msg.json.action ) { + case 'analyze': + w.analyze(msg.json.hostname, msg.json.url, msg.json.analyze); + + break; + case 'get prefs': + return { + analyzeJavaScript: prefs.getBoolPref('analyzeJavaScript'), + analyzeOnLoad: prefs.getBoolPref('analyzeOnLoad') + }; + + break; + } msg = null; } @@ -249,11 +277,11 @@ if ( prefs.getBoolPref('addonBar') ) { $('#wappalyzer-container').prependTo($('#wappalyzer-addonbar')); - $('#wappalyzer-addonbar').show(); + $('#wappalyzer-addonbar').attr('collapsed', 'false'); } else { $('#wappalyzer-container').prependTo($('#urlbar-icons')); - $('#wappalyzer-addonbar').hide(); + $('#wappalyzer-addonbar').attr('collapsed', 'true'); } } @@ -264,35 +292,11 @@ // Menu items var prefix = '#wappalyzer-menu-'; - $(prefix + 'icons') - .attr('checked', prefs.getBoolPref('showIcons') ? 'true' : 'false') - .bind('command', function() { - prefs.setBoolPref('showIcons', !prefs.getBoolPref('showIcons')); - - $(this).attr('checked', prefs.getBoolPref('showIcons') ? 'true' : 'false'); - - w.driver.displayApps(); - }); - $(prefix + 'preferences' ) .bind('command', function() { w.driver.goToURL({ url: 'chrome://wappalyzer/content/xul/preferences.xul' }) }); - $(prefix + 'addonbar' ) - .attr('checked', prefs.getBoolPref('addonBar') ? 'true' : 'false') - .bind('command', function() { - prefs.setBoolPref('addonBar', !prefs.getBoolPref('addonBar')); - - $(this).attr('checked', prefs.getBoolPref('addonBar') ? 'true' : 'false'); - - container(); - - if ( prefs.getBoolPref('addonBar') ) { - alert(strings.getString('wappalyzer.addonBar')); - } - }); - $(prefix + 'feedback') .bind('command', function() { w.driver.goToURL({ url: w.config.websiteURL + 'contact' }) diff --git a/drivers/firefox/content/xul/preferences.xul b/drivers/firefox/content/xul/preferences.xul index 3ae791df0..e1d3aee1c 100755 --- a/drivers/firefox/content/xul/preferences.xul +++ b/drivers/firefox/content/xul/preferences.xul @@ -6,8 +6,15 @@ - + + + + + + + + @@ -37,153 +44,114 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/firefox/content/xul/wappalyzer.xul b/drivers/firefox/content/xul/wappalyzer.xul index aa398aafc..cad1a1a3d 100755 --- a/drivers/firefox/content/xul/wappalyzer.xul +++ b/drivers/firefox/content/xul/wappalyzer.xul @@ -18,8 +18,6 @@ - - diff --git a/drivers/firefox/defaults/preferences/defaults.js b/drivers/firefox/defaults/preferences/defaults.js index 266967266..d7bac6b36 100644 --- a/drivers/firefox/defaults/preferences/defaults.js +++ b/drivers/firefox/defaults/preferences/defaults.js @@ -1,37 +1,40 @@ -pref('extensions.wappalyzer.debug', false); -pref('extensions.wappalyzer.showIcons', true); -pref('extensions.wappalyzer.tracking', true); -pref('extensions.wappalyzer.addonBar', false); -pref('extensions.wappalyzer.version', ''); +pref('extensions.wappalyzer.debug', false); +pref('extensions.wappalyzer.showIcons', true); +pref('extensions.wappalyzer.tracking', true); +pref('extensions.wappalyzer.addonBar', false); +pref('extensions.wappalyzer.version', ''); +pref('extensions.wappalyzer.analyzeHeaders', true); +pref('extensions.wappalyzer.analyzeJavaScript', true); +pref('extensions.wappalyzer.analyzeOnLoad', true); -pref('extensions.wappalyzer.cat1', true); -pref('extensions.wappalyzer.cat2', true); -pref('extensions.wappalyzer.cat3', true); -pref('extensions.wappalyzer.cat4', true); -pref('extensions.wappalyzer.cat5', true); -pref('extensions.wappalyzer.cat6', true); -pref('extensions.wappalyzer.cat7', true); -pref('extensions.wappalyzer.cat8', true); -pref('extensions.wappalyzer.cat9', true); -pref('extensions.wappalyzer.cat10', true); -pref('extensions.wappalyzer.cat11', true); -pref('extensions.wappalyzer.cat12', true); -pref('extensions.wappalyzer.cat13', true); -pref('extensions.wappalyzer.cat14', true); -pref('extensions.wappalyzer.cat15', true); -pref('extensions.wappalyzer.cat16', true); -pref('extensions.wappalyzer.cat17', true); -pref('extensions.wappalyzer.cat18', true); -pref('extensions.wappalyzer.cat19', true); -pref('extensions.wappalyzer.cat20', true); -pref('extensions.wappalyzer.cat21', true); -pref('extensions.wappalyzer.cat22', true); -pref('extensions.wappalyzer.cat23', true); -pref('extensions.wappalyzer.cat24', true); -pref('extensions.wappalyzer.cat25', true); -pref('extensions.wappalyzer.cat26', true); -pref('extensions.wappalyzer.cat27', true); -pref('extensions.wappalyzer.cat28', true); -pref('extensions.wappalyzer.cat29', true); -pref('extensions.wappalyzer.cat30', true); -pref('extensions.wappalyzer.cat31', true); +pref('extensions.wappalyzer.cat1', true); +pref('extensions.wappalyzer.cat2', true); +pref('extensions.wappalyzer.cat3', true); +pref('extensions.wappalyzer.cat4', true); +pref('extensions.wappalyzer.cat5', true); +pref('extensions.wappalyzer.cat6', true); +pref('extensions.wappalyzer.cat7', true); +pref('extensions.wappalyzer.cat8', true); +pref('extensions.wappalyzer.cat9', true); +pref('extensions.wappalyzer.cat10', true); +pref('extensions.wappalyzer.cat11', true); +pref('extensions.wappalyzer.cat12', true); +pref('extensions.wappalyzer.cat13', true); +pref('extensions.wappalyzer.cat14', true); +pref('extensions.wappalyzer.cat15', true); +pref('extensions.wappalyzer.cat16', true); +pref('extensions.wappalyzer.cat17', true); +pref('extensions.wappalyzer.cat18', true); +pref('extensions.wappalyzer.cat19', true); +pref('extensions.wappalyzer.cat20', true); +pref('extensions.wappalyzer.cat21', true); +pref('extensions.wappalyzer.cat22', true); +pref('extensions.wappalyzer.cat23', true); +pref('extensions.wappalyzer.cat24', true); +pref('extensions.wappalyzer.cat25', true); +pref('extensions.wappalyzer.cat26', true); +pref('extensions.wappalyzer.cat27', true); +pref('extensions.wappalyzer.cat28', true); +pref('extensions.wappalyzer.cat29', true); +pref('extensions.wappalyzer.cat30', true); +pref('extensions.wappalyzer.cat31', true); diff --git a/drivers/firefox/install.rdf b/drivers/firefox/install.rdf index bbdc06d4d..27e02141c 100644 --- a/drivers/firefox/install.rdf +++ b/drivers/firefox/install.rdf @@ -3,7 +3,7 @@ wappalyzer@crunchlabz.com - 2.3.4 + 2.4.0 2 true @@ -16,9 +16,9 @@ - + chrome://wappalyzer/content/xul/preferences.xul + 3 + chrome://wappalyzer/skin/images/icon128x128.png Wappalyzer Identifies software on the web. diff --git a/drivers/firefox/locale/de-DE/wappalyzer.dtd b/drivers/firefox/locale/de-DE/wappalyzer.dtd index 408e5fd3c..ecddadb74 100755 --- a/drivers/firefox/locale/de-DE/wappalyzer.dtd +++ b/drivers/firefox/locale/de-DE/wappalyzer.dtd @@ -1,49 +1,51 @@ - - + + - - - - - - - + + + + + + + + + + + - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/firefox/locale/en-US/wappalyzer.dtd b/drivers/firefox/locale/en-US/wappalyzer.dtd index 47e3f5b14..904f910ee 100755 --- a/drivers/firefox/locale/en-US/wappalyzer.dtd +++ b/drivers/firefox/locale/en-US/wappalyzer.dtd @@ -1,48 +1,52 @@ - - + + - - - - - - + + + + + + + + + + + + - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/firefox/locale/fr-FR/wappalyzer.dtd b/drivers/firefox/locale/fr-FR/wappalyzer.dtd index c81afc93f..5f2dd2bcf 100644 --- a/drivers/firefox/locale/fr-FR/wappalyzer.dtd +++ b/drivers/firefox/locale/fr-FR/wappalyzer.dtd @@ -1,48 +1,51 @@ - - + + - - - - - - + + + + + + + + + + + - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/firefox/locale/nl-NL/wappalyzer.dtd b/drivers/firefox/locale/nl-NL/wappalyzer.dtd index 6f51023c5..852d4af44 100755 --- a/drivers/firefox/locale/nl-NL/wappalyzer.dtd +++ b/drivers/firefox/locale/nl-NL/wappalyzer.dtd @@ -1,47 +1,50 @@ - - + + - - - - - - + + + + + + + + + + + - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/drivers/firefox/icon.png b/drivers/firefox/skin/images/icon128x128.png similarity index 100% rename from drivers/firefox/icon.png rename to drivers/firefox/skin/images/icon128x128.png diff --git a/drivers/firefox/skin/images/icon64x64.png b/drivers/firefox/skin/images/icon64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..58d6a0edc06a77cda16ce6732f786658c9217381 GIT binary patch literal 5039 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 FV1n|mo%#R( literal 0 HcmV?d00001