| |
@@ -0,0 +1,208 @@
|
| |
+ /*
|
| |
+ * GNU LibreJS - A browser add-on to block nonfree nontrivial JavaScript.
|
| |
+ *
|
| |
+ * Copyright (C) 2018 Giorgio Maone <giorgio@maone.net>
|
| |
+ *
|
| |
+ * This file is part of GNU LibreJS.
|
| |
+ *
|
| |
+ * GNU LibreJS 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.
|
| |
+ *
|
| |
+ * GNU LibreJS 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 GNU LibreJS. If not, see <http://www.gnu.org/licenses/>.
|
| |
+ */
|
| |
+ "use strict";
|
| |
+
|
| |
+ describe("LibreJS' components", () => {
|
| |
+ let LibreJS = browser.extension.getBackgroundPage().LibreJS;
|
| |
+ let license = {
|
| |
+ id: 'GPL-3.0',
|
| |
+ url: 'http://www.gnu.org/licenses/gpl-3.0.html',
|
| |
+ magnet: 'magnet:?xt=urn:btih:1f739d935676111cfff4b4693e3816e664797050&dn=gpl-3.0.txt',
|
| |
+ };
|
| |
+ let unknownLicense = {
|
| |
+ id: 'Acme-proprietary-1.5',
|
| |
+ url: 'http://www.acme.com/license-1.5.html',
|
| |
+ magnet: 'magnet:?xt=urn:btih:2f739d935676111cfff4b4693e3816e664797050&dn=acme-1.5.txt'
|
| |
+ };
|
| |
+
|
| |
+ let trivial = "1+1";
|
| |
+ let nontrivial = `function nt() { document.documentElement.innerHTML=""; nt(); }`;
|
| |
+ let licensed = `// @license ${license.magnet} ${license.id}\n${nontrivial}\n// @license-end`;
|
| |
+ let unknownLicensed = `// @license ${unknownLicense.magnet} ${unknownLicense.id}\n${nontrivial}\n// @license-end`;
|
| |
+ let malformedLicensed = `// @license\n${nontrivial}`;
|
| |
+
|
| |
+ let tab, documentUrl;
|
| |
+
|
| |
+ beforeAll(async () => {
|
| |
+ let url = browser.extension.getURL("/test/resources/index.html");
|
| |
+ tab = (await browser.tabs.query({url}))[0] || (await browser.tabs.create({url}));
|
| |
+ documentUrl = url;
|
| |
+ });
|
| |
+
|
| |
+ describe("The external script source processor", () => {
|
| |
+ let url = "https://www.gnu.org/mock-script.js";
|
| |
+
|
| |
+ let processScript = async (source, whitelisted = false) =>
|
| |
+ await LibreJS.handle_script({
|
| |
+ text: source,
|
| |
+ request: {url, tabId: tab.id, documentUrl, frameId: 0},
|
| |
+ }, whitelisted);
|
| |
+
|
| |
+ it("should accept whitelisted scripts", async () => {
|
| |
+ expect(await processScript(nontrivial, true) || nontrivial).toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block trivial scripts too", async () => {
|
| |
+ let processed = await processScript(trivial);
|
| |
+ expect(processed || trivial).not.toContain(trivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block non-trivial scripts", async () => {
|
| |
+ let processed = await processScript(nontrivial);
|
| |
+ expect(processed || nontrivial).not.toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should accept scripts with known free license tags", async () => {
|
| |
+ let processed = await processScript(licensed);
|
| |
+ expect(processed || licensed).toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block scripts with unknown license tags", async () => {
|
| |
+ let processed = await processScript(unknownLicensed);
|
| |
+ expect(processed).not.toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block scripts with malformed license tags", async () => {
|
| |
+ let processed = await processScript(malformedLicensed);
|
| |
+ expect(processed).not.toContain(nontrivial);
|
| |
+ });
|
| |
+ });
|
| |
+
|
| |
+ describe("The HTML processor", () => {
|
| |
+ let processHtml =
|
| |
+ async (html, whitelisted = false) =>
|
| |
+ LibreJS.editHtml(html, tab.url, tab.id, 0, whitelisted);
|
| |
+
|
| |
+ let addScript = (html, script, before = "</head>") =>
|
| |
+ html.replace(before, `<script>${script}</script>${before}`);
|
| |
+
|
| |
+ function extractScripts(html, def = "") {
|
| |
+ let matches = html && html.match(/<script>[^]*?<\/script>/g);
|
| |
+ return matches && matches.join("") || def;
|
| |
+ }
|
| |
+
|
| |
+ let html, nontrivialInHtml;
|
| |
+ beforeAll(async () => {
|
| |
+ html = (await browser.tabs.executeScript(tab.id, {
|
| |
+ runAt: "document_start",
|
| |
+ code: "document.documentElement.outerHTML"
|
| |
+ }))[0];
|
| |
+ nontrivialInHtml = addScript(html, nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should not modify scriptless documents", async () => {
|
| |
+ expect(await processHtml(html)).toBeNull();
|
| |
+ });
|
| |
+
|
| |
+ it("should not modify whitelisted documents", async () => {
|
| |
+ expect(await processHtml(nontrivialInHtml, true)).toBeNull();
|
| |
+ });
|
| |
+
|
| |
+ it("should accept trivial scripts", async () => {
|
| |
+ let trivialInHtml = addScript(html, trivial);
|
| |
+ let processed = await processHtml(trivialInHtml);
|
| |
+ expect(extractScripts(processed, trivial)).toContain(trivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block non-trivial scripts", async () => {
|
| |
+ let processed = await processHtml(nontrivialInHtml);
|
| |
+ expect(extractScripts(processed, nontrivial)).not.toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should accept scripts with known free license tags", async () => {
|
| |
+ let licensedInHtml = addScript(html, licensed);
|
| |
+ let processed = await processHtml(licensedInHtml);
|
| |
+ expect(extractScripts(processed, licensed)).toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block scripts with unknown license tags", async () => {
|
| |
+ let unknownInHtml = addScript(html, unknownLicensed);
|
| |
+ let processed = await processHtml(unknownInHtml);
|
| |
+ expect(extractScripts(processed, nontrivial)).not.toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should block scripts with malformed license tags", async () => {
|
| |
+ let malformedInHtml = addScript(html, malformedLicensed);
|
| |
+ let processed = await processHtml(malformedInHtml);
|
| |
+ expect(extractScripts(processed, nontrivial)).not.toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should accept scripts on globally licensed pages", async () => {
|
| |
+ let globalLicense = `/* @licstart The following is the entire license notice
|
| |
+ for the JavaScript code in this page.
|
| |
+ -- Some free license --
|
| |
+ @licend The above is the entire license notice for the JavaScript code in this page. */`;
|
| |
+
|
| |
+ let licensed = addScript(nontrivialInHtml, globalLicense, "<script>");
|
| |
+ let processed = await processHtml(html);
|
| |
+ expect(extractScripts(processed, licensed)).toContain(nontrivial);
|
| |
+ });
|
| |
+
|
| |
+ it("should discriminate trivial, non-trivial and licensed mixed on the same page", async () => {
|
| |
+ let mixedPage = addScript(addScript(nontrivialInHtml, trivial), licensed);
|
| |
+ let processed = await processHtml(mixedPage);
|
| |
+ expect(processed).not.toBeNull();
|
| |
+ let scripts = extractScripts(processed, nontrivial);
|
| |
+ expect(scripts).toContain(trivial);
|
| |
+ expect(scripts).toContain(licensed);
|
| |
+ expect(scripts.replace(licensed, "")).not.toContain(nontrivial);
|
| |
+ });
|
| |
+ });
|
| |
+
|
| |
+ describe("The external (Web Labels) license checker", () => {
|
| |
+ let {ExternalLicenses} = LibreJS;
|
| |
+ let check;
|
| |
+
|
| |
+ beforeAll(async () => {
|
| |
+ let args = {tabId: tab.id, frameId: 0, documentUrl};
|
| |
+ let resolve = url => new URL(url, documentUrl).href;
|
| |
+ check = async url => await ExternalLicenses.check(Object.assign({url: resolve(url)}, args));
|
| |
+ await browser.tabs.executeScript(tab.id, {
|
| |
+ file: "/content/externalLicenseChecker.js"
|
| |
+ });
|
| |
+ });
|
| |
+
|
| |
+ it("should recognize free licenses", async () => {
|
| |
+ let scriptInfo = await check("jquery.js");
|
| |
+ console.debug(scriptInfo);
|
| |
+ expect(scriptInfo.free).toBeTruthy();
|
| |
+ });
|
| |
+ it("should accept scripts if any of multiple licenses is free", async () => {
|
| |
+ let scriptInfo = await check("app-trilicensed.js");
|
| |
+ console.debug(scriptInfo);
|
| |
+ expect(scriptInfo.free).toBeTruthy();
|
| |
+ });
|
| |
+ it("should block scripts declaring only proprietary license(s)", async () => {
|
| |
+ let scriptInfo = await check("proprietary.js");
|
| |
+ console.debug(scriptInfo);
|
| |
+ expect(scriptInfo.free).toBeFalsy();
|
| |
+ });
|
| |
+ it("should block scripts not declaring any license", async () => {
|
| |
+ let scriptInfo = await check("tracker.js");
|
| |
+ console.debug(scriptInfo);
|
| |
+ expect(scriptInfo).toBeNull();
|
| |
+ });
|
| |
+ });
|
| |
+ afterAll(async () => {
|
| |
+ await browser.tabs.remove(tab.id);
|
| |
+ browser.tabs.update((await browser.tabs.getCurrent()).id, {active: true});
|
| |
+ });
|
| |
+ });
|
| |
This PR adds an extensible, BDD, Jasmine-based test suite for the HTML processor, the external script processor and the external license checker (web labels) components.
From the new "TESTING" section of the README:
An automated test suite runs automatically in its own tab whenever the extension is loaded as a "temporary add-on" from about:debugging.
Otherwise (if included in the xpi, see BUILD above) it can be launched from the UI by clicking the [Automated self test...] button.