diff options
| author | Einar Egilsson <einar@einaregilsson.com> | 2015-09-24 11:25:45 +0000 | 
|---|---|---|
| committer | Einar Egilsson <einar@einaregilsson.com> | 2015-09-24 11:25:45 +0000 | 
| commit | 3adcb7ae1654928a8a86de4cf329dcd912bcbb33 (patch) | |
| tree | 6a992508214e6d6a31af400e5ff8a192203e5fd0 | |
| parent | f432a10a164e9a32f7bb915e5ca8cef5489f3ccd (diff) | |
3.0.1. Fix Firefox disabling issues, simplify the chrome api shim, make things a bit more robust
| -rw-r--r-- | js/background.js | 4 | ||||
| -rw-r--r-- | js/firefox/background-shim.js | 31 | ||||
| -rw-r--r-- | js/firefox/content-script-proxy.js | 38 | ||||
| -rw-r--r-- | js/firefox/extension-storage.jsm | 4 | ||||
| -rw-r--r-- | js/firefox/page-shim.js | 27 | ||||
| -rw-r--r-- | js/popup-scriptload.js | 13 | ||||
| -rw-r--r-- | js/redirector-scriptload.js | 19 | ||||
| -rw-r--r-- | js/redirector.js | 342 | ||||
| -rw-r--r-- | manifest.json | 2 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | popup.html | 4 | ||||
| -rw-r--r-- | redirector.html | 10 | 
12 files changed, 77 insertions, 419 deletions
| 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('<script src="' + path + '"></script>'); +} + +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('<script src="' + path + '"></script>'); +} + +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(); diff --git a/manifest.json b/manifest.json index aa2fbf7..75e0ea1 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@    "manifest_version": 2,    "name": "Redirector",    "description": "Automatically redirect pages based on user-defined rules. E.g. always redirect an article url to its printer-friendly version.", -  "version": "3.0", +  "version": "3.0.1",    "icons": {   "16": "images/icon-active-16.png",                 "32": "images/icon-active-32.png", diff --git a/package.json b/package.json index 5951062..d525e7f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@    "title": "Redirector",    "name": "redirector",    "id" : "redirector@einaregilsson.com", -  "version": "3.0.0", +  "version": "3.0.1",    "homepage" : "http://einaregilsson.com/redirector",    "icon" : "resource://redirector-at-einaregilsson-dot-com/images/icon-active-48.png",    "icon64" : "resource://redirector-at-einaregilsson-dot-com/images/icon-active-64.png", @@ -4,9 +4,7 @@  		<title>REDIRECTOR</title>  		<link rel="stylesheet" href="css/popup.css" />  		<meta charset="UTF-8"> -		<script src="js/firefox/page-shim.js"></script> -		<script src="js/angular.min.js"></script> -		<script src="js/popup.js"></script> +		<script src="js/popup-scriptload.js"></script>  	</head>  	<body ng-app="popupApp" ng-controller="PopupCtrl">  		<h1>REDIRECTOR</h1> diff --git a/redirector.html b/redirector.html index 7b381e2..eb67002 100644 --- a/redirector.html +++ b/redirector.html @@ -6,15 +6,7 @@  		<link rel="stylesheet" href="css/redirector.css" />  		<!-- ☈ -->  		<link rel="shortcut icon" href="images/icon-active-32.png"> -		<script src="js/firefox/page-shim.js"></script> -		<script src="js/angular.min.js"></script> -		<script src="js/redirect.js"></script> -		<script src="js/app.js"></script> -		<script src="js/controllers/redirectorpage.js"></script> -		<script src="js/controllers/editredirect.js"></script> -		<script src="js/controllers/deleteredirect.js"></script> -		<script src="js/controllers/importexport.js"></script> -		<script src="js/controllers/listredirects.js"></script> +		<script src="js/redirector-scriptload.js"></script>  	</head>  	<body ng-app="redirectorApp" ng-controller="RedirectorPageCtrl">  		<div id="cover" ng-show="showEditForm || showDeleteForm"></div> | 
