diff options
author | Nik Nyby <nikolas@gnu.org> | 2015-01-17 17:12:36 -0500 |
---|---|---|
committer | Nik Nyby <nikolas@gnu.org> | 2015-01-17 17:12:36 -0500 |
commit | ada88090ead2c3b9d0804794c5f20f9b24d1c2b1 (patch) | |
tree | 2838a7eee6c5d74094216acebd86915e0ea1de42 /lib/js_load_observer | |
download | librejsxul-ada88090ead2c3b9d0804794c5f20f9b24d1c2b1.tar.lz librejsxul-ada88090ead2c3b9d0804794c5f20f9b24d1c2b1.tar.xz librejsxul-ada88090ead2c3b9d0804794c5f20f9b24d1c2b1.zip |
Import to new git repository
The old repository was using almost 100mb of space because of all
the unnecessary files in the history. So I've imported the code to a
new git repository. Unfortunately the history isn't viewable from this
repository anymore. To see what happened with LibreJS before 2015, see
the old Bazaar repo here: http://bzr.savannah.gnu.org/lh/librejs/
Diffstat (limited to 'lib/js_load_observer')
-rw-r--r-- | lib/js_load_observer/js_load_observer.js | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/lib/js_load_observer/js_load_observer.js b/lib/js_load_observer/js_load_observer.js new file mode 100644 index 0000000..a8792e2 --- /dev/null +++ b/lib/js_load_observer/js_load_observer.js @@ -0,0 +1,143 @@ +/** + * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript. + * * + * Copyright (C) 2011, 2012, 2013, 2014 Loic J. Duros + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +var {Cc, Ci, Cu, Cm, Cr} = require("chrome"); + +var observerService = Cc["@mozilla.org/observer-service;1"] +.getService(Ci.nsIObserverService); + +var acceptedScripts = require("script_entries/accepted_scripts").acceptedScripts; +var allowedRef = require('http_observer/allowed_referrers').allowedReferrers; + +var urlHandler = require("url_handler/url_handler"); + +var ScriptAnalyzer = function() { + // the URL of the current page. + this.pageURL = null; +}; + +/* + * analyzeScriptBeforeExec + * + * Ensure that the script is found in the acceptedScript before + * allowing to execute it. + * + */ +ScriptAnalyzer.prototype.analyzeScriptBeforeExec = function (e) { + if (typeof e.target.textContent === 'undefined') { + throw new TypeError('event.target must be a script element'); + } + console.debug('analyzeScriptBeforeExec executed'); + + var script = e.target, isAccepted; + var text = script.src ? + script.src : script.textContent.substring(0,100); + var notif = require("ui/notification") + .createNotification(text).notification; + this.pageURL = urlHandler.removeFragment(script.ownerDocument.URL); + if (!allowedRef.urlInAllowedReferrers(this.pageURL)) { + + if (script.src !== undefined && script.src !== '') { + isAccepted = this.checkExternalScript(script); + } else { + isAccepted = this.checkInlineScript(script); + } + + if (isAccepted === false && + !(/^(file:\/\/|chrome:\/\/|about\:)/.test(this.pageURL)) + ) { + console.debug(this.pageURL); + // file:// types of pages are allowed. + + // set invalid type so that the script is detected + // by LibreJS as blocked (although it's blocked using + // preventDefault(). + script.setAttribute('type', 'librejs/blocked'); + //script.setAttribute('data-librejs-blocked', 'dynamically'); + script.setAttribute('data-librejs-blocked-src', script.src); + script.removeAttribute('src'); + + e.preventDefault(); + return false; + } else { + console.debug("script is accepted", script.src); + script.setAttribute('data-librejs-accepted', 'dynamically'); + return true; + } + + } else { + return true; + } + + return false; +}; + +ScriptAnalyzer.prototype.checkExternalScript = function (script) { + var url = urlHandler.resolve(this.pageURL, script.src); + + if (this.isScriptAccepted(url, false)) { + // url in src attribute is found as accepted. + return true; + } + + else { + // the script hasn't been accepted before. + // block it. + console.debug("script is not accepted", script.src); + return false; + } + +}; + +ScriptAnalyzer.prototype.checkInlineScript = function (script) { + return this.isScriptAccepted(script.text, true); +}; + +ScriptAnalyzer.prototype.isScriptAccepted = function (contents, inline) { + + if (!acceptedScripts.isFound(this.pageURL, {'inline': inline, 'contents': contents})) { + return false; + } + + else { + return true; + } +}; + +var scriptAnalyzer = new ScriptAnalyzer(); + +var jsLoadObserver = { + observe: function (domWindow) { + domWindow.document.addEventListener( + "beforescriptexecute", + scriptAnalyzer.analyzeScriptBeforeExec.bind(scriptAnalyzer), + false); + } +}; + +observerService.addObserver(jsLoadObserver, + 'content-document-global-created', + false); + +exports.removeJsLoadObserver = function () { + observerService.removeObserver(jsLoadObserver, + 'content-document-global-created'); + console.debug('removing jsLoadObserver'); +}; |