From 3adcb7ae1654928a8a86de4cf329dcd912bcbb33 Mon Sep 17 00:00:00 2001 From: Einar Egilsson Date: Thu, 24 Sep 2015 11:25:45 +0000 Subject: 3.0.1. Fix Firefox disabling issues, simplify the chrome api shim, make things a bit more robust --- js/background.js | 4 +- js/firefox/background-shim.js | 31 +++- js/firefox/content-script-proxy.js | 38 ----- js/firefox/extension-storage.jsm | 4 + js/firefox/page-shim.js | 27 ++- js/popup-scriptload.js | 13 ++ js/redirector-scriptload.js | 19 +++ js/redirector.js | 342 ------------------------------------- 8 files changed, 73 insertions(+), 405 deletions(-) delete mode 100644 js/firefox/content-script-proxy.js create mode 100644 js/popup-scriptload.js create mode 100644 js/redirector-scriptload.js delete mode 100644 js/redirector.js (limited to 'js') diff --git a/js/background.js b/js/background.js index a87293a..e66be8f 100644 --- a/js/background.js +++ b/js/background.js @@ -12,14 +12,17 @@ log.enabled = false; var isFirefox = false; if (typeof chrome == 'undefined') { + console.log('Creating fake chrome...'); isFirefox = true; var firefoxShim = require('./firefox/background-shim'); chrome = firefoxShim.chrome; Redirect = firefoxShim.Redirect; log = firefoxShim.log; exports.onUnload = function (reason) { + log('Unloading (' + reason + '), removing listeners'); redirectEvent.removeListener(checkRedirects); chrome.storage.onChanged.removeListener(monitorChanges); + chrome.storage.clearCache(); //<-Firefox specific }; } //Hopefully Firefox will fix this at some point and we can just use onBeforeRequest everywhere... @@ -193,7 +196,6 @@ function setUpRedirectListener() { chrome.storage.local.get({redirects:[]}, function(obj) { var redirects = obj.redirects; - if (redirects.length == 0) { log('No redirects defined, not setting up listener'); return; diff --git a/js/firefox/background-shim.js b/js/firefox/background-shim.js index 5598920..d43d662 100644 --- a/js/firefox/background-shim.js +++ b/js/firefox/background-shim.js @@ -106,6 +106,10 @@ var chrome = { } }, + clearCache : function() { + ExtensionStorage.clearCache(); + }, + onChanged : { addListener : function(listener) { ExtensionStorage.addOnChangedListener(extensionId, listener); @@ -136,7 +140,11 @@ var panel = panels.Panel({ width: 200, height: 110, contentURL: makeUrl('popup.html'), - contentScriptFile : makeUrl('js/firefox/content-script-proxy.js'), + contentScriptFile : [ + makeUrl('js/firefox/page-shim.js'), + makeUrl('js/angular.min.js'), + makeUrl('js/popup.js') + ], onHide: function() { button.state('window', {checked: false}); } @@ -145,9 +153,6 @@ var panel = panels.Panel({ function attachedPage(worker) { function sendReply(originalMessage, reply) { var msg = {messageId:originalMessage.messageId, payload:reply}; - if (typeof log == 'undefined') { - Cu.reportError('LOG IS DEAD DEAD DEAD'); - } log('background sending message: ' + JSON.stringify(msg)); worker.port.emit('message', msg); } @@ -210,10 +215,20 @@ function attachedPage(worker) { attachedPage(panel); pageMod.PageMod({ - include: makeUrl('redirector.html'), - contentScriptFile: makeUrl('js/firefox/content-script-proxy.js'), - contentScriptWhen: 'start', - onAttach : attachedPage + include: makeUrl('redirector.html'), + contentScriptFile: [ + makeUrl("js/firefox/page-shim.js"), + makeUrl("js/angular.min.js"), + makeUrl("js/redirect.js"), + makeUrl("js/app.js"), + makeUrl("js/controllers/redirectorpage.js"), + makeUrl("js/controllers/editredirect.js"), + makeUrl("js/controllers/deleteredirect.js"), + makeUrl("js/controllers/importexport.js"), + makeUrl("js/controllers/listredirects.js") + ], + contentScriptWhen: 'start', + onAttach : attachedPage }); diff --git a/js/firefox/content-script-proxy.js b/js/firefox/content-script-proxy.js deleted file mode 100644 index c56de29..0000000 --- a/js/firefox/content-script-proxy.js +++ /dev/null @@ -1,38 +0,0 @@ -// This file listens to messages - -function log(msg) { - self.port.emit('log', msg); -} - -function receiveWindowMessage(message) { - if (message.data.sender !== 'page') { - return; - } - - if (message.data.logMessage) { - //Special handling for log messages. - log(message.data.logMessage); - return; - } - - log('proxy got page message: ' + JSON.stringify(message.data)); - - //Forward the message to the background script - self.port.emit('message', message.data); -} - -window.addEventListener('message', receiveWindowMessage); - -function receiveMessage(message) { - log('proxy got chrome message: ' + JSON.stringify(message)); - window.postMessage(message, '*'); -} -self.port.on('message', receiveMessage); - -function cleanup() { - window.removeEventListener('message', receiveWindowMessage); - self.port.removeListener('message', receiveMessage); - self.port.removeListener('detach', cleanup); -} - -self.port.on('detach', cleanup); diff --git a/js/firefox/extension-storage.jsm b/js/firefox/extension-storage.jsm index 02c59a3..f102b6f 100644 --- a/js/firefox/extension-storage.jsm +++ b/js/firefox/extension-storage.jsm @@ -36,6 +36,10 @@ this.ExtensionStorage = { return Path.join(this.extensionDir, extensionId, "storage.js"); }, + clearCache : function() { + this.cache = new Map(); + }, + read(extensionId) { if (this.cache.has(extensionId)) { return this.cache.get(extensionId); diff --git a/js/firefox/page-shim.js b/js/firefox/page-shim.js index dd2361b..6496910 100644 --- a/js/firefox/page-shim.js +++ b/js/firefox/page-shim.js @@ -1,32 +1,27 @@ (function() { - //Communication functions for - - if (typeof chrome !== 'undefined') { - return; - } function log(msg) { - window.postMessage({sender:'page', logMessage: msg}, '*'); + self.port.emit('log', msg); } + var parts = location.pathname.split('/'); + var urlName = parts[parts.length-1]; var messageId = 1; var callbacks = {}; function send(type, message, callback) { var id = messageId++; - window.postMessage({sender:'page', url:location.href, messageId:id, messageType:type, payload:message}, '*'); - callbacks[id] = callback; + self.port.emit('message', {url:urlName, messageId:id, messageType:type, payload:message}); + callbacks[id] = callback || function(){}; } - window.addEventListener('message', function(message) { - if (message.data.sender == 'page') { - return; //Ignore messages we sent ourselves - } - log('page got message: ' + JSON.stringify(message.data)); + + self.port.on('message', function(message) { + log('page got message: ' + JSON.stringify(message)); - var callback = callbacks[message.data.messageId]; + var callback = callbacks[message.messageId]; if (callback) { - callback(message.data.payload); - delete callbacks[message.data.messageId]; + callback(message.payload); + delete callbacks[message.messageId]; } }); diff --git a/js/popup-scriptload.js b/js/popup-scriptload.js new file mode 100644 index 0000000..bcb5370 --- /dev/null +++ b/js/popup-scriptload.js @@ -0,0 +1,13 @@ + +//Do it this way to make the Firefox version work with content +//scripts and all that crap. Will be removed when everything +//can use the WebExtensions API. + +function loadScript(path) { + document.write(''); +} + +if (typeof chrome !== 'undefined') { + loadScript("js/angular.min.js"); + loadScript("js/popup.js"); +} diff --git a/js/redirector-scriptload.js b/js/redirector-scriptload.js new file mode 100644 index 0000000..844576d --- /dev/null +++ b/js/redirector-scriptload.js @@ -0,0 +1,19 @@ + +//Do it this way to make the Firefox version work with content +//scripts and all that crap. Will be removed when everything +//can use the WebExtensions API. + +function loadScript(path) { + document.write(''); +} + +if (typeof chrome !== 'undefined') { + loadScript("js/angular.min.js"); + loadScript("js/redirect.js"); + loadScript("js/app.js"); + loadScript("js/controllers/redirectorpage.js"); + loadScript("js/controllers/editredirect.js"); + loadScript("js/controllers/deleteredirect.js"); + loadScript("js/controllers/importexport.js"); + loadScript("js/controllers/listredirects.js"); +} diff --git a/js/redirector.js b/js/redirector.js deleted file mode 100644 index 86e07a2..0000000 --- a/js/redirector.js +++ /dev/null @@ -1,342 +0,0 @@ -Components.utils.import("chrome://redirector/content/js/xpcom.js"); -Components.utils.import("chrome://redirector/content/js/redirect.js"); -Components.utils.import("chrome://redirector/content/js/redirectorprefs.js"); - -var EXPORTED_SYMBOLS = ['Redirector']; - -Redirector = { - - get enabled() { - return this._prefs && this._prefs.enabled; - }, - - set enabled(value) { - if (this._prefs) { - this._prefs.enabled = value; - } - }, - - get redirectCount() { - return this._list.length; - }, - - toString : function() { - return "Redirector"; - }, - - addRedirect : function(redirect) { - this._list.push(redirect); - this.save(); - }, - - debug : function(msg) { - if (this._prefs.debugEnabled) { - ConsoleService.logStringMessage('REDIRECTOR: ' + msg); - } - }, - - deleteRedirect : function(redirect) { - this._list.splice(this._list.indexOf(redirect), 1); - this.save(); - }, - - exportRedirects : function(file) { - const PR_WRONLY = 0x02; - const PR_CREATE_FILE = 0x08; - const PR_TRUNCATE = 0x20; - - var fileStream = new FileOutputStream(file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0644, 0); - var stream = new ConverterOutputStream(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); - var rjson = { createdBy : 'Redirector v' + this._prefs.version, createdAt : new Date(), redirects :[]}; - for each (var re in this._list) { - rjson.redirects.push(re.toObject()); - } - stream.writeString(JSON.stringify(rjson, null, 4)); - stream.close(); - }, - - getRedirectAt : function(index) { - return this._list[index]; - }, - - //Get the redirect url for the given url. This will not check if we are enabled, and - //not do any verification on the url, just assume that it is a good string url that is for http/s - getRedirectUrl : function(url) { - this.debug("Checking " + url); - - for each (var redirect in this._list) { - var result = redirect.getMatch(url); - if (result.isExcludeMatch) { - this.debug(url + ' matched exclude pattern ' + redirect.excludePattern + ' so the redirect ' + redirect.includePattern + ' will not be used'); - } else if (result.isDisabledMatch) { - this.debug(url + ' matched pattern ' + redirect.includePattern + ' but the redirect is disabled'); - } else if (result.isMatch) { - redirectUrl = this._makeAbsoluteUrl(url, result.redirectTo); - - //check for loops... - result = redirect.getMatch(redirectUrl); - if (result.isMatch) { - var msg = this._getFormattedString('invalidRedirectText', [redirect.includePattern, url, redirectUrl]); - this.debug(msg); - redirect.disabled = true; - this.save(); - ConsoleService.logStringMessage('Redirector: ' + msg); - } else { - this.debug('Redirecting ' + url + ' to ' + redirectUrl); - return redirectUrl; - } - } - } - return null; - }, - - QueryInterface: function(iid) { - if (iid.equals(Ci.nsISupports) || iid.equals(Ci.nsIContentPolicy) || iid.equals(Ci.nsIChannelEventSink)) { - return this; - } - throw Cr.NS_ERROR_NO_INTERFACE; - }, - - _getRedirectsFile : function() { - var file = DirectoryService.get("ProfD", Ci.nsIFile); - file.append('redirector.rjson'); - return file; - }, - - handleUpgrades : function(){ - var currentVersion = '2.7.1'; - this._list = []; - - if (this._prefs.version == currentVersion) { - return; - } - //Here update checks are handled - - try { - var branch = PrefService.getBranch("extensions.redirector."); - var data = branch.getCharPref("redirects"); - } catch(e) { - this._prefs.version = currentVersion; - return; - } - var arr; - this._list = []; - if (data != '') { - for each (redirectString in data.split(':::')) { - if (!redirectString || !redirectString.split) { - continue; - this.debug('Invalid old redirect: ' + redirectString); - } - var parts = redirectString.split(',,,'); - if (parts.length < 5) { - throw Error("Invalid serialized redirect, too few fields: " + redirectString); - } - var redirect = new Redirect(); - redirect._init.apply(redirect, parts); - this._list.push(redirect); - } - this.save(); - this._list = []; //Let the real loading start this properly - } - branch.deleteBranch('redirects'); - this._prefs.version = currentVersion; - }, - - importRedirects : function(file) { - var fileStream = new FileInputStream(file, 0x01, 0444, 0); - var stream = new ConverterInputStream(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); - var str = {}; - var rjson = ''; - while (stream.readString(4096, str) != 0) { - rjson += str.value; - } - stream.close(); - var importCount = 0, existsCount = 0; - rjson = JSON.parse(rjson); - for each (var rd in rjson.redirects) { - var redirect = new Redirect(); - redirect.fromObject(rd); - if (this._containsRedirect(redirect)) { - existsCount++; - } else { - this._list.push(redirect); - importCount++; - } - } - this.save(); - return importCount | (existsCount << 16); - }, - - save : function() { - var file = this._getRedirectsFile(); - this.exportRedirects(file); - }, - - sortRedirects : function(sortFunc) { - this._list.sort(sortFunc); - this.save(); - }, - - // nsIContentPolicy implementation - shouldLoad: function(contentType, contentLocation, requestOrigin, aContext, mimeTypeGuess, extra) { - if (contentLocation.scheme != "http" && contentLocation.scheme != "https") { - return Ci.nsIContentPolicy.ACCEPT; - } //Immediately, otherwise we will log all sorts of crap - - this.debug('nsIContentPolicy::ShouldLoad ' + contentLocation.spec); - try { - //This is also done in getRedirectUrl, but we want to exit as quickly as possible for performance - if (!this._prefs.enabled) { - return Ci.nsIContentPolicy.ACCEPT; - } - - if (contentType != Ci.nsIContentPolicy.TYPE_DOCUMENT) { - return Ci.nsIContentPolicy.ACCEPT; - } - - if (contentLocation.scheme != "http" && contentLocation.scheme != "https") { - return Ci.nsIContentPolicy.ACCEPT; - } - - if (!aContext || !aContext.loadURI) { - return Ci.nsIContentPolicy.ACCEPT; - } - - var redirectUrl = this.getRedirectUrl(contentLocation.spec); - - if (!redirectUrl) { - return Ci.nsIContentPolicy.ACCEPT; - } - - aContext.loadURI(redirectUrl, requestOrigin, null); - return Ci.nsIContentPolicy.REJECT_REQUEST; - } catch(e) { - this.debug(e); - } - - }, - - shouldProcess: function(contentType, contentLocation, requestOrigin, insecNode, mimeType, extra) { - return Ci.nsIContentPolicy.ACCEPT; - }, - //end nsIContentPolicy - - //nsIChannelEventSink implementation - - //For FF4.0. Got this from a thread about adblock plus, https://adblockplus.org/forum/viewtopic.php?t=5895 - asyncOnChannelRedirect: function(oldChannel, newChannel, flags, redirectCallback) { - this.onChannelRedirect(oldChannel, newChannel, flags); - redirectCallback.onRedirectVerifyCallback(0); - }, - - onChannelRedirect: function(oldChannel, newChannel, flags) - { - try { - let newLocation = newChannel.URI.spec; - this.debug('nsIChannelEventSink::onChannelRedirect ' + newLocation); - - if (!(newChannel.loadFlags & Ci.nsIChannel.LOAD_DOCUMENT_URI)) { - //We only redirect documents... - return; - } - - if (!this._prefs.enabled) { - return; - } - - if (!newLocation) { - return; - } - let callbacks = []; - if (newChannel.notificationCallbacks) { - callbacks.push(newChannel.notificationCallbacks); - } - if (newChannel.loadGroup && newChannel.loadGroup.notificationCallbacks) { - callbacks.push(newChannel.loadGroup.notificationCallbacks); - } - var win; - var webNav; - for each (let callback in callbacks) - { - try { - win = callback.getInterface(Ci.nsILoadContext).associatedWindow; - webNav = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation); - break; - } catch(e) {} - } - if (!webNav) { - return; - } - var redirectUrl = this.getRedirectUrl(newLocation); - - if (redirectUrl) { - webNav.loadURI(redirectUrl,null,null,null,null); - throw Cr.NS_BASE_STREAM_WOULD_BLOCK; //Throw this because the real error we should throw shows up in console... - } - - } catch (e if (e != Cr.NS_BASE_STREAM_WOULD_BLOCK)) { - // We shouldn't throw exceptions here - this will prevent the redirect. - this.debug("Redirector: Unexpected error in onChannelRedirect: " + e + "\n"); - } - }, - //end nsIChannelEventSink - - //Private members and methods - - _prefs : null, - _list : null, - _strings : null, - - init : function() { - if (this._prefs) { - this._prefs.dispose(); - } - this._prefs = new RedirectorPrefs(); - this.debug('REDIRECTOR CREATED'); - //Check if we need to update existing redirects - var data = this._prefs.redirects; - var version = this._prefs.version; - this._loadStrings(); - this._list = []; - this.handleUpgrades(); - var redirectsFile = this._getRedirectsFile(); - if (redirectsFile.exists()) { - this.importRedirects(redirectsFile); - } - }, - - _loadStrings : function() { - var src = 'chrome://redirector/locale/redirector.properties'; - var appLocale = LocaleService.getApplicationLocale(); - this._strings = StringBundleService.createBundle(src, appLocale); - }, - - _containsRedirect : function(redirect) { - for each (var existing in this._list) { - if (existing.equals(redirect)) { - return true; - } - } - return false; - }, - - _getString : function(name) { - return this._strings.GetStringFromName(name); - }, - - _getFormattedString : function(name, params) { - return this._strings.formatStringFromName(name, params, params.length); - }, - - _makeAbsoluteUrl : function(currentUrl, relativeUrl) { - - if (relativeUrl.match(/https?:/)) { - return relativeUrl; - } - - var uri = IOService.newURI(currentUrl, null, null); - return uri.resolve(relativeUrl); - } -}; - -Redirector.init(); -- cgit v1.2.3