mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 01:02:08 +01:00
remove firefox/legacy platform, it now has its own branch: firefox-legacy
This commit is contained in:
parent
3923520b87
commit
443010efdc
19 changed files with 0 additions and 5649 deletions
250
platform/firefox/bootstrap.js
vendored
250
platform/firefox/bootstrap.js
vendored
|
@ -1,250 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014-2017 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* global ADDON_UNINSTALL, APP_SHUTDOWN */
|
|
||||||
/* exported startup, shutdown, install, uninstall */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
|
||||||
|
|
||||||
// Accessing the context of the background page:
|
|
||||||
// var win = Services.appShell.hiddenDOMWindow.document.querySelector('iframe[src*=ublock0]').contentWindow;
|
|
||||||
|
|
||||||
let windowlessBrowser = null;
|
|
||||||
let windowlessBrowserPL = null;
|
|
||||||
let bgProcess = null;
|
|
||||||
let version;
|
|
||||||
const hostName = 'ublock0';
|
|
||||||
const restartListener = {
|
|
||||||
get messageManager() {
|
|
||||||
return Cc['@mozilla.org/parentprocessmessagemanager;1']
|
|
||||||
.getService(Ci.nsIMessageListenerManager);
|
|
||||||
},
|
|
||||||
|
|
||||||
receiveMessage: function() {
|
|
||||||
shutdown();
|
|
||||||
startup();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
function startup(data/*, reason*/) {
|
|
||||||
if ( data !== undefined ) {
|
|
||||||
version = data.version;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Already started?
|
|
||||||
if ( bgProcess !== null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
waitForHiddenWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
function createBgProcess(parentDocument) {
|
|
||||||
bgProcess = parentDocument.documentElement.appendChild(
|
|
||||||
parentDocument.createElementNS('http://www.w3.org/1999/xhtml', 'iframe')
|
|
||||||
);
|
|
||||||
bgProcess.setAttribute(
|
|
||||||
'src',
|
|
||||||
'chrome://' + hostName + '/content/background.html#' + version
|
|
||||||
);
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIMessageListenerManager#addMessageListener%28%29
|
|
||||||
// "If the same listener registers twice for the same message, the
|
|
||||||
// "second registration is ignored."
|
|
||||||
restartListener.messageManager.addMessageListener(
|
|
||||||
hostName + '-restart',
|
|
||||||
restartListener
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getWindowlessBrowserFrame(appShell) {
|
|
||||||
windowlessBrowser = appShell.createWindowlessBrowser(true);
|
|
||||||
windowlessBrowser.QueryInterface(Ci.nsIInterfaceRequestor);
|
|
||||||
let webProgress = windowlessBrowser.getInterface(Ci.nsIWebProgress);
|
|
||||||
let XPCOMUtils = Cu.import('resource://gre/modules/XPCOMUtils.jsm', null).XPCOMUtils;
|
|
||||||
windowlessBrowserPL = {
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([
|
|
||||||
Ci.nsIWebProgressListener,
|
|
||||||
Ci.nsIWebProgressListener2,
|
|
||||||
Ci.nsISupportsWeakReference
|
|
||||||
]),
|
|
||||||
onStateChange: function(wbp, request, stateFlags/*, status*/) {
|
|
||||||
if ( !request ) { return; }
|
|
||||||
if ( stateFlags & Ci.nsIWebProgressListener.STATE_STOP ) {
|
|
||||||
webProgress.removeProgressListener(windowlessBrowserPL);
|
|
||||||
windowlessBrowserPL = null;
|
|
||||||
createBgProcess(windowlessBrowser.document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
webProgress.addProgressListener(windowlessBrowserPL, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
|
|
||||||
windowlessBrowser.document.location = "data:application/vnd.mozilla.xul+xml;charset=utf-8,<window%20id='" + hostName + "-win'/>";
|
|
||||||
}
|
|
||||||
|
|
||||||
function waitForHiddenWindow() {
|
|
||||||
let appShell = Cc['@mozilla.org/appshell/appShellService;1']
|
|
||||||
.getService(Ci.nsIAppShellService);
|
|
||||||
|
|
||||||
let isReady = function() {
|
|
||||||
var hiddenDoc;
|
|
||||||
|
|
||||||
try {
|
|
||||||
hiddenDoc = appShell.hiddenDOMWindow &&
|
|
||||||
appShell.hiddenDOMWindow.document;
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not test against `loading`: it does appear `readyState` could be
|
|
||||||
// undefined if looked up too early.
|
|
||||||
if ( !hiddenDoc || hiddenDoc.readyState !== 'complete' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In theory, it should be possible to create a windowless browser
|
|
||||||
// immediately, without waiting for the hidden window to have loaded
|
|
||||||
// completely. However, in practice, on Windows this seems to lead
|
|
||||||
// to a broken Firefox appearance. To avoid this, we only create the
|
|
||||||
// windowless browser here. We'll use that rather than the hidden
|
|
||||||
// window for the actual background page (windowless browsers are
|
|
||||||
// also what the webextension implementation in Firefox uses for
|
|
||||||
// background pages).
|
|
||||||
let { Services } = Cu.import('resource://gre/modules/Services.jsm', null);
|
|
||||||
if ( Services.vc.compare(Services.appinfo.platformVersion, '27') >= 0 ) {
|
|
||||||
getWindowlessBrowserFrame(appShell);
|
|
||||||
} else {
|
|
||||||
createBgProcess(hiddenDoc);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( isReady() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/749
|
|
||||||
// Poll until the proper environment is set up -- or give up eventually.
|
|
||||||
// We poll frequently early on but relax poll delay as time pass.
|
|
||||||
|
|
||||||
let tryDelay = 5;
|
|
||||||
let trySum = 0;
|
|
||||||
// https://trac.torproject.org/projects/tor/ticket/19438
|
|
||||||
// Try for a longer period.
|
|
||||||
let tryMax = 600011;
|
|
||||||
let timer = Cc['@mozilla.org/timer;1']
|
|
||||||
.createInstance(Ci.nsITimer);
|
|
||||||
|
|
||||||
let checkLater = function() {
|
|
||||||
trySum += tryDelay;
|
|
||||||
if ( trySum >= tryMax ) {
|
|
||||||
timer = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
timer.init(timerObserver, tryDelay, timer.TYPE_ONE_SHOT);
|
|
||||||
tryDelay *= 2;
|
|
||||||
if ( tryDelay > 503 ) {
|
|
||||||
tryDelay = 503;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var timerObserver = {
|
|
||||||
observe: function() {
|
|
||||||
timer.cancel();
|
|
||||||
if ( isReady() ) {
|
|
||||||
timer = null;
|
|
||||||
} else {
|
|
||||||
checkLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
checkLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
function shutdown(data, reason) {
|
|
||||||
if ( reason === APP_SHUTDOWN ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( bgProcess !== null ) {
|
|
||||||
bgProcess.parentNode.removeChild(bgProcess);
|
|
||||||
bgProcess = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( windowlessBrowser !== null ) {
|
|
||||||
// close() does not exist for older versions of Firefox.
|
|
||||||
if ( typeof windowlessBrowser.close === 'function' ) {
|
|
||||||
windowlessBrowser.close();
|
|
||||||
}
|
|
||||||
windowlessBrowser = null;
|
|
||||||
windowlessBrowserPL = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( data === undefined ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the restartObserver only when the extension is being disabled
|
|
||||||
restartListener.messageManager.removeMessageListener(
|
|
||||||
hostName + '-restart',
|
|
||||||
restartListener
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
function install(/*aData, aReason*/) {
|
|
||||||
// https://bugzil.la/719376
|
|
||||||
Cc['@mozilla.org/intl/stringbundle;1']
|
|
||||||
.getService(Ci.nsIStringBundleService)
|
|
||||||
.flushBundles();
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/Add-ons/Bootstrapped_extensions#uninstall
|
|
||||||
// "if you have code in uninstall it will not run, you MUST run some code
|
|
||||||
// "in the install function, at the least you must set arguments on the
|
|
||||||
// "install function so like: function install(aData, aReason) {} then
|
|
||||||
// "uninstall WILL WORK."
|
|
||||||
|
|
||||||
function uninstall(aData, aReason) {
|
|
||||||
if ( aReason !== ADDON_UNINSTALL ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// https://github.com/gorhill/uBlock/issues/84
|
|
||||||
// "Add cleanup task to remove local storage settings when uninstalling"
|
|
||||||
// To cleanup vAPI.localStorage in vapi-common.js
|
|
||||||
// As I get more familiar with FF API, will find out whetehr there was
|
|
||||||
// a better way to do this.
|
|
||||||
Cu.import('resource://gre/modules/Services.jsm', null)
|
|
||||||
.Services.prefs.getBranch('extensions.' + hostName + '.')
|
|
||||||
.deleteBranch('');
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1 +0,0 @@
|
||||||
content ublock0 ./
|
|
|
@ -1,46 +0,0 @@
|
||||||
#uBlock0-legacy-button {
|
|
||||||
list-style-image: url('../img/browsericons/icon24.svg');
|
|
||||||
}
|
|
||||||
#uBlock0-legacy-button.off {
|
|
||||||
list-style-image: url('../img/browsericons/icon24-off.svg');
|
|
||||||
}
|
|
||||||
|
|
||||||
toolbar[iconsize="small"] #uBlock0-legacy-button {
|
|
||||||
list-style-image: url('../img/browsericons/icon16.svg');
|
|
||||||
}
|
|
||||||
toolbar[iconsize="small"] #uBlock0-legacy-button.off {
|
|
||||||
list-style-image: url('../img/browsericons/icon16-off.svg');
|
|
||||||
}
|
|
||||||
#uBlock0-legacy-button[badge]::before {
|
|
||||||
background: #555;
|
|
||||||
color: #fff;
|
|
||||||
content: attr(badge);
|
|
||||||
font: bold 10px sans-serif;
|
|
||||||
margin-top: -2px;
|
|
||||||
padding: 0 2px;
|
|
||||||
position: fixed;
|
|
||||||
}
|
|
||||||
/* This hack required because if the before content changes it de-pops the
|
|
||||||
popup (without firing any events). So just hide it instead. Note, can't
|
|
||||||
actually *hide* it, or the same thing happens.
|
|
||||||
**/
|
|
||||||
#uBlock0-legacy-button[badge=""]::before {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Override off state when in palette */
|
|
||||||
toolbarpaletteitem #uBlock0-legacy-button.off {
|
|
||||||
list-style-image: url('../img/browsericons/icon24.svg');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Override badge when in palette */
|
|
||||||
toolbarpaletteitem #uBlock0-legacy-button[badge]::before {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prevent pale moon from showing the arrow underneath the button */
|
|
||||||
/* https://github.com/chrisaljoudi/uBlock/issues/1449#issuecomment-112112761 */
|
|
||||||
#uBlock0-legacy-button .toolbarbutton-menu-dropmarker {
|
|
||||||
display: none;
|
|
||||||
-moz-box-orient: horizontal;
|
|
||||||
}
|
|
|
@ -1,623 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014-2017 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* exported processObserver */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/800
|
|
||||||
this.EXPORTED_SYMBOLS = [
|
|
||||||
'contentObserver',
|
|
||||||
'processObserver',
|
|
||||||
'LocationChangeListener'
|
|
||||||
];
|
|
||||||
|
|
||||||
const {interfaces: Ci, utils: Cu} = Components;
|
|
||||||
const {Services} = Cu.import('resource://gre/modules/Services.jsm', null);
|
|
||||||
const {XPCOMUtils} = Cu.import('resource://gre/modules/XPCOMUtils.jsm', null);
|
|
||||||
|
|
||||||
const hostName = Services.io.newURI(Components.stack.filename, null, null).host;
|
|
||||||
const rpcEmitterName = hostName + ':child-process-message';
|
|
||||||
|
|
||||||
//Cu.import('resource://gre/modules/Console.jsm'); // Firefox >= 44
|
|
||||||
//Cu.import('resource://gre/modules/devtools/Console.jsm'); // Firefox < 44
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
const getMessageManager = function(win) {
|
|
||||||
let iface = win
|
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDocShell)
|
|
||||||
.sameTypeRootTreeItem
|
|
||||||
.QueryInterface(Ci.nsIDocShell)
|
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor);
|
|
||||||
|
|
||||||
try {
|
|
||||||
return iface.getInterface(Ci.nsIContentFrameMessageManager);
|
|
||||||
} catch (ex) {
|
|
||||||
// This can throw. It appears `shouldLoad` can be called *after* a
|
|
||||||
// tab has been closed. For example, a case where this happens all
|
|
||||||
// the time (FF38):
|
|
||||||
// - Open twitter.com (assuming you have an account and are logged in)
|
|
||||||
// - Close twitter.com
|
|
||||||
// There will be an exception raised when `shouldLoad` is called
|
|
||||||
// to process a XMLHttpRequest with URL `https://twitter.com/i/jot`
|
|
||||||
// fired from `https://twitter.com/`, *after* the tab is closed.
|
|
||||||
// In such case, `win` is `about:blank`.
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/2014
|
|
||||||
// Have a dictionary of hostnames for which there are script tag filters. This
|
|
||||||
// allow for coarse-testing before firing a synchronous message to the
|
|
||||||
// parent process. Script tag filters are not very common, so this allows
|
|
||||||
// to skip the blocking of the child process most of the time.
|
|
||||||
|
|
||||||
var scriptTagFilterer = (function() {
|
|
||||||
var scriptTagHostnames;
|
|
||||||
|
|
||||||
var getCpmm = function() {
|
|
||||||
var svc = Services;
|
|
||||||
if ( !svc ) { return; }
|
|
||||||
var cpmm = svc.cpmm;
|
|
||||||
if ( cpmm ) { return cpmm; }
|
|
||||||
cpmm = Components.classes['@mozilla.org/childprocessmessagemanager;1'];
|
|
||||||
if ( cpmm ) { return cpmm.getService(Ci.nsISyncMessageSender); }
|
|
||||||
};
|
|
||||||
|
|
||||||
var getScriptTagHostnames = function() {
|
|
||||||
if ( scriptTagHostnames ) {
|
|
||||||
return scriptTagHostnames;
|
|
||||||
}
|
|
||||||
var cpmm = getCpmm();
|
|
||||||
if ( !cpmm ) { return; }
|
|
||||||
var r = cpmm.sendSyncMessage(rpcEmitterName, { fnName: 'getScriptTagHostnames' });
|
|
||||||
if ( Array.isArray(r) && Array.isArray(r[0]) ) {
|
|
||||||
scriptTagHostnames = new Set(r[0]);
|
|
||||||
}
|
|
||||||
return scriptTagHostnames;
|
|
||||||
};
|
|
||||||
|
|
||||||
var getScriptTagFilters = function(details) {
|
|
||||||
let cpmm = getCpmm();
|
|
||||||
if ( !cpmm ) { return; }
|
|
||||||
let r = cpmm.sendSyncMessage(rpcEmitterName, {
|
|
||||||
fnName: 'getScriptTagFilters',
|
|
||||||
rootURL: details.rootURL,
|
|
||||||
frameURL: details.frameURL,
|
|
||||||
frameHostname: details.frameHostname
|
|
||||||
});
|
|
||||||
if ( Array.isArray(r) ) {
|
|
||||||
return r[0];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var regexFromHostname = function(details) {
|
|
||||||
// If target hostname has no script tag filter, no point querying
|
|
||||||
// chrome process.
|
|
||||||
var hostnames = getScriptTagHostnames();
|
|
||||||
if ( !hostnames ) { return; }
|
|
||||||
var hn = details.frameHostname, pos, entity;
|
|
||||||
for (;;) {
|
|
||||||
if ( hostnames.has(hn) ) {
|
|
||||||
return getScriptTagFilters(details);
|
|
||||||
}
|
|
||||||
pos = hn.indexOf('.');
|
|
||||||
if ( pos === -1 ) { break; }
|
|
||||||
entity = hn.slice(0, pos) + '.*';
|
|
||||||
if ( hostnames.has(entity) ) {
|
|
||||||
return getScriptTagFilters(details);
|
|
||||||
}
|
|
||||||
hn = hn.slice(pos + 1);
|
|
||||||
if ( hn === '' ) { break; }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var reset = function() {
|
|
||||||
scriptTagHostnames = undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
get: regexFromHostname,
|
|
||||||
reset: reset
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var contentObserver = {
|
|
||||||
classDescription: 'content-policy for ' + hostName,
|
|
||||||
classID: Components.ID('{7afbd130-cbaf-46c2-b944-f5d24305f484}'),
|
|
||||||
contractID: '@' + hostName + '/content-policy;1',
|
|
||||||
ACCEPT: Ci.nsIContentPolicy.ACCEPT,
|
|
||||||
REJECT: Ci.nsIContentPolicy.REJECT_REQUEST,
|
|
||||||
MAIN_FRAME: Ci.nsIContentPolicy.TYPE_DOCUMENT,
|
|
||||||
SUB_FRAME: Ci.nsIContentPolicy.TYPE_SUBDOCUMENT,
|
|
||||||
contentBaseURI: 'chrome://' + hostName + '/content/js/',
|
|
||||||
cpMessageName: hostName + ':shouldLoad',
|
|
||||||
popupMessageName: hostName + ':shouldLoadPopup',
|
|
||||||
ignoredPopups: new WeakMap(),
|
|
||||||
uniquePopupEventId: 1,
|
|
||||||
uniqueSandboxId: 1,
|
|
||||||
modernFirefox: Services.vc.compare(Services.appinfo.platformVersion, '44') > 0,
|
|
||||||
|
|
||||||
get componentRegistrar() {
|
|
||||||
return Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
|
||||||
},
|
|
||||||
|
|
||||||
get categoryManager() {
|
|
||||||
return Components.classes['@mozilla.org/categorymanager;1']
|
|
||||||
.getService(Ci.nsICategoryManager);
|
|
||||||
},
|
|
||||||
|
|
||||||
QueryInterface: XPCOMUtils.generateQI([
|
|
||||||
Ci.nsIFactory,
|
|
||||||
Ci.nsIObserver,
|
|
||||||
Ci.nsIContentPolicy,
|
|
||||||
Ci.nsISupportsWeakReference
|
|
||||||
]),
|
|
||||||
|
|
||||||
createInstance: function(outer, iid) {
|
|
||||||
if ( outer ) {
|
|
||||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.QueryInterface(iid);
|
|
||||||
},
|
|
||||||
|
|
||||||
register: function() {
|
|
||||||
Services.obs.addObserver(this, 'document-element-inserted', true);
|
|
||||||
Services.obs.addObserver(this, 'content-document-global-created', true);
|
|
||||||
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=1232354
|
|
||||||
// For modern versions of Firefox, the frameId/parentFrameId
|
|
||||||
// information can be found in channel.loadInfo of the HTTP observer.
|
|
||||||
if ( this.modernFirefox !== true ) {
|
|
||||||
this.componentRegistrar.registerFactory(
|
|
||||||
this.classID,
|
|
||||||
this.classDescription,
|
|
||||||
this.contractID,
|
|
||||||
this
|
|
||||||
);
|
|
||||||
this.categoryManager.addCategoryEntry(
|
|
||||||
'content-policy',
|
|
||||||
this.contractID,
|
|
||||||
this.contractID,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
unregister: function() {
|
|
||||||
Services.obs.removeObserver(this, 'document-element-inserted');
|
|
||||||
Services.obs.removeObserver(this, 'content-document-global-created');
|
|
||||||
|
|
||||||
if ( this.modernFirefox !== true ) {
|
|
||||||
this.componentRegistrar.unregisterFactory(this.classID, this);
|
|
||||||
this.categoryManager.deleteCategoryEntry(
|
|
||||||
'content-policy',
|
|
||||||
this.contractID,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getFrameId: function(win) {
|
|
||||||
return win
|
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils)
|
|
||||||
.outerWindowID;
|
|
||||||
},
|
|
||||||
|
|
||||||
// https://bugzil.la/612921
|
|
||||||
shouldLoad: function(type, location, origin, context) {
|
|
||||||
// For whatever reason, sometimes the global scope is completely
|
|
||||||
// uninitialized at this point. Repro steps:
|
|
||||||
// - Launch FF with uBlock enabled
|
|
||||||
// - Disable uBlock
|
|
||||||
// - Enable uBlock
|
|
||||||
// - Services and all other global variables are undefined
|
|
||||||
// Hopefully will eventually understand why this happens.
|
|
||||||
if ( Services === undefined || !context ) {
|
|
||||||
return this.ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !location.schemeIs('http') && !location.schemeIs('https') ) {
|
|
||||||
return this.ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( type === this.MAIN_FRAME ) {
|
|
||||||
context = context.contentWindow || context;
|
|
||||||
} else if ( type === this.SUB_FRAME ) {
|
|
||||||
context = context.contentWindow;
|
|
||||||
} else {
|
|
||||||
context = (context.ownerDocument || context).defaultView;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1893
|
|
||||||
// I don't know why this happens. I observed that when it occurred, the
|
|
||||||
// resource was not seen by the HTTP observer, as if it was a spurious
|
|
||||||
// call to shouldLoad().
|
|
||||||
if ( !context ) {
|
|
||||||
return this.ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The context for the toolbar popup is an iframe element here,
|
|
||||||
// so check context.top instead of context
|
|
||||||
if ( !context.top || !context.location ) {
|
|
||||||
return this.ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
let messageManager = getMessageManager(context);
|
|
||||||
if ( messageManager === null ) {
|
|
||||||
return this.ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isTopContext = context === context.top;
|
|
||||||
var parentFrameId;
|
|
||||||
if ( isTopContext ) {
|
|
||||||
parentFrameId = -1;
|
|
||||||
} else if ( context.parent === context.top ) {
|
|
||||||
parentFrameId = 0;
|
|
||||||
} else {
|
|
||||||
parentFrameId = this.getFrameId(context.parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
let rpcData = this.rpcData;
|
|
||||||
rpcData.frameId = isTopContext ? 0 : this.getFrameId(context);
|
|
||||||
rpcData.pFrameId = parentFrameId;
|
|
||||||
rpcData.type = type;
|
|
||||||
rpcData.url = location.spec;
|
|
||||||
|
|
||||||
//console.log('shouldLoad: type=' + type + ' url=' + location.spec);
|
|
||||||
if ( typeof messageManager.sendRpcMessage === 'function' ) {
|
|
||||||
// https://bugzil.la/1092216
|
|
||||||
messageManager.sendRpcMessage(this.cpMessageName, rpcData);
|
|
||||||
} else {
|
|
||||||
// Compatibility for older versions
|
|
||||||
messageManager.sendSyncMessage(this.cpMessageName, rpcData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.ACCEPT;
|
|
||||||
},
|
|
||||||
|
|
||||||
// Reuse object to avoid repeated memory allocation.
|
|
||||||
rpcData: { frameId: 0, pFrameId: -1, type: 0, url: '' },
|
|
||||||
|
|
||||||
initContentScripts: function(win, create) {
|
|
||||||
let messager = getMessageManager(win);
|
|
||||||
let sandboxId = hostName + ':sb:' + this.uniqueSandboxId++;
|
|
||||||
let sandbox;
|
|
||||||
|
|
||||||
if ( create ) {
|
|
||||||
let sandboxName = [
|
|
||||||
win.location.href.slice(0, 100),
|
|
||||||
win.document.title.slice(0, 100)
|
|
||||||
].join(' | ');
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uMatrix/issues/325
|
|
||||||
// "Pass sameZoneAs to sandbox constructor to make GCs cheaper"
|
|
||||||
sandbox = Cu.Sandbox([win], {
|
|
||||||
sameZoneAs: win.top,
|
|
||||||
sandboxName: sandboxId + '[' + sandboxName + ']',
|
|
||||||
sandboxPrototype: win,
|
|
||||||
wantComponents: false,
|
|
||||||
wantXHRConstructor: false
|
|
||||||
});
|
|
||||||
|
|
||||||
sandbox.getScriptTagFilters = function(details) {
|
|
||||||
return scriptTagFilterer.get(details);
|
|
||||||
};
|
|
||||||
|
|
||||||
sandbox.injectScript = function(script) {
|
|
||||||
let svc = Services;
|
|
||||||
// Sandbox appears void.
|
|
||||||
// I've seen this happens, need to investigate why.
|
|
||||||
if ( svc === undefined ) { return; }
|
|
||||||
svc.scriptloader.loadSubScript(script, sandbox);
|
|
||||||
};
|
|
||||||
|
|
||||||
let canUserStyles = (function() {
|
|
||||||
try {
|
|
||||||
return win.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils)
|
|
||||||
.loadSheetUsingURIString instanceof Function;
|
|
||||||
} catch(ex) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
})();
|
|
||||||
|
|
||||||
if ( canUserStyles ) {
|
|
||||||
sandbox.injectCSS = function(sheetURI) {
|
|
||||||
try {
|
|
||||||
let wu = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
wu.loadSheetUsingURIString(sheetURI, wu.USER_SHEET);
|
|
||||||
} catch(ex) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sandbox.removeCSS = function(sheetURI) {
|
|
||||||
try {
|
|
||||||
let wu = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIDOMWindowUtils);
|
|
||||||
wu.removeSheetUsingURIString(sheetURI, wu.USER_SHEET);
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
sandbox.topContentScript = win === win.top;
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_loading_and_lifetime#Unloading_frame_scripts
|
|
||||||
// The goal is to have content scripts removed from web pages. This
|
|
||||||
// helps remove traces of uBlock from memory when disabling/removing
|
|
||||||
// the addon.
|
|
||||||
// For example, this takes care of:
|
|
||||||
// https://github.com/gorhill/uBlock/commit/ea4faff383789053f423498c1f1165c403fde7c7#commitcomment-11964137
|
|
||||||
// > "gets the whole selected tab flashing"
|
|
||||||
sandbox.outerShutdown = function() {
|
|
||||||
sandbox.removeMessageListener();
|
|
||||||
sandbox.addMessageListener =
|
|
||||||
sandbox.getScriptTagFilters =
|
|
||||||
sandbox.injectCSS =
|
|
||||||
sandbox.injectScript =
|
|
||||||
sandbox.outerShutdown =
|
|
||||||
sandbox.removeCSS =
|
|
||||||
sandbox.removeMessageListener =
|
|
||||||
sandbox.sendAsyncMessage = function(){};
|
|
||||||
sandbox.vAPI = {};
|
|
||||||
messager = null;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sandbox = win;
|
|
||||||
}
|
|
||||||
|
|
||||||
sandbox._sandboxId_ = sandboxId;
|
|
||||||
sandbox.sendAsyncMessage = messager.sendAsyncMessage;
|
|
||||||
|
|
||||||
sandbox.addMessageListener = function(callback) {
|
|
||||||
if ( sandbox._messageListener_ ) {
|
|
||||||
sandbox.removeMessageListener();
|
|
||||||
}
|
|
||||||
|
|
||||||
sandbox._messageListener_ = function(message) {
|
|
||||||
callback(message.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
sandbox._broadcastListener_ = function(message) {
|
|
||||||
// https://github.com/gorhill/uBlock/issues/2014
|
|
||||||
if ( sandbox.topContentScript ) {
|
|
||||||
let details;
|
|
||||||
try { details = JSON.parse(message.data); } catch (ex) {}
|
|
||||||
let msg = details && details.msg || {};
|
|
||||||
if ( msg.what === 'staticFilteringDataChanged' ) {
|
|
||||||
if ( scriptTagFilterer ) {
|
|
||||||
scriptTagFilterer.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(message.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
messager.addMessageListener(
|
|
||||||
sandbox._sandboxId_,
|
|
||||||
sandbox._messageListener_
|
|
||||||
);
|
|
||||||
messager.addMessageListener(
|
|
||||||
hostName + ':broadcast',
|
|
||||||
sandbox._broadcastListener_
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
sandbox.removeMessageListener = function() {
|
|
||||||
if ( !sandbox._messageListener_ ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// It throws sometimes, mostly when the popup closes
|
|
||||||
try {
|
|
||||||
messager.removeMessageListener(
|
|
||||||
sandbox._sandboxId_,
|
|
||||||
sandbox._messageListener_
|
|
||||||
);
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
messager.removeMessageListener(
|
|
||||||
hostName + ':broadcast',
|
|
||||||
sandbox._broadcastListener_
|
|
||||||
);
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
|
||||||
|
|
||||||
sandbox._messageListener_ = sandbox._broadcastListener_ = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
return sandbox;
|
|
||||||
},
|
|
||||||
|
|
||||||
injectOtherContentScripts: function(doc, sandbox) {
|
|
||||||
let docReady = (e) => {
|
|
||||||
let doc = e.target;
|
|
||||||
doc.removeEventListener(e.type, docReady, true);
|
|
||||||
if ( doc.querySelector('a[href^="abp:"],a[href^="https://subscribe.adblockplus.org/?"]') ) {
|
|
||||||
Services.scriptloader.loadSubScript(this.contentBaseURI + 'scriptlets/subscriber.js', sandbox);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if ( doc.readyState === 'loading') {
|
|
||||||
doc.addEventListener('DOMContentLoaded', docReady, true);
|
|
||||||
} else {
|
|
||||||
docReady({ target: doc, type: 'DOMContentLoaded' });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
ignorePopup: function(e) {
|
|
||||||
if ( e.isTrusted === false ) { return; }
|
|
||||||
let contObs = contentObserver;
|
|
||||||
contObs.ignoredPopups.set(this, true);
|
|
||||||
this.removeEventListener('keydown', contObs.ignorePopup, true);
|
|
||||||
this.removeEventListener('mousedown', contObs.ignorePopup, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
lookupPopupOpener: function(popup) {
|
|
||||||
for (;;) {
|
|
||||||
let opener = popup.opener;
|
|
||||||
if ( !opener ) { return; }
|
|
||||||
if ( opener.top ) { opener = opener.top; }
|
|
||||||
if ( opener === popup ) { return; }
|
|
||||||
if ( !opener.location ) { return; }
|
|
||||||
if ( this.reValidPopups.test(opener.location.protocol) ) {
|
|
||||||
return opener;
|
|
||||||
}
|
|
||||||
// https://github.com/uBlockOrigin/uAssets/issues/255
|
|
||||||
// - Mind chained about:blank popups.
|
|
||||||
if ( opener.location.href !== 'about:blank' ) { return; }
|
|
||||||
popup = opener;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
reValidPopups: /^(?:blob|data|https?|javascript):/,
|
|
||||||
reMustInjectScript: /^(?:file|https?):/,
|
|
||||||
|
|
||||||
observe: function(subject, topic) {
|
|
||||||
// For whatever reason, sometimes the global scope is completely
|
|
||||||
// uninitialized at this point. Repro steps:
|
|
||||||
// - Launch FF with uBlock enabled
|
|
||||||
// - Disable uBlock
|
|
||||||
// - Enable uBlock
|
|
||||||
// - Services and all other global variables are undefined
|
|
||||||
// Hopefully will eventually understand why this happens.
|
|
||||||
if ( Services === undefined ) { return; }
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/2290
|
|
||||||
if ( topic === 'content-document-global-created' ) {
|
|
||||||
if ( subject !== subject.top || !subject.opener ) { return; }
|
|
||||||
if ( this.ignoredPopups.has(subject) ) { return; }
|
|
||||||
let opener = this.lookupPopupOpener(subject);
|
|
||||||
if ( !opener ) { return; }
|
|
||||||
subject.addEventListener('keydown', this.ignorePopup, true);
|
|
||||||
subject.addEventListener('mousedown', this.ignorePopup, true);
|
|
||||||
let popupMessager = getMessageManager(subject);
|
|
||||||
if ( !popupMessager ) { return; }
|
|
||||||
let openerMessager = getMessageManager(opener);
|
|
||||||
if ( !openerMessager ) { return; }
|
|
||||||
popupMessager.sendAsyncMessage(this.popupMessageName, {
|
|
||||||
id: this.uniquePopupEventId,
|
|
||||||
popup: true
|
|
||||||
});
|
|
||||||
openerMessager.sendAsyncMessage(this.popupMessageName, {
|
|
||||||
id: this.uniquePopupEventId,
|
|
||||||
opener: true
|
|
||||||
});
|
|
||||||
this.uniquePopupEventId += 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// topic === 'document-element-inserted'
|
|
||||||
|
|
||||||
let doc = subject;
|
|
||||||
let win = doc.defaultView || null;
|
|
||||||
if ( win === null ) { return; }
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/260
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Document/contentType
|
|
||||||
// "Non-standard, only supported by Gecko. To be used in
|
|
||||||
// "chrome code (i.e. Extensions and XUL applications)."
|
|
||||||
// TODO: We may have to exclude more types, for now let's be
|
|
||||||
// conservative and focus only on the one issue reported, i.e. let's
|
|
||||||
// not test against 'text/html'.
|
|
||||||
if ( doc.contentType.startsWith('image/') ) { return; }
|
|
||||||
|
|
||||||
let loc = win.location;
|
|
||||||
if ( this.reMustInjectScript.test(loc.protocol) === false ) {
|
|
||||||
if ( loc.protocol === 'chrome:' && loc.host === hostName ) {
|
|
||||||
this.initContentScripts(win);
|
|
||||||
}
|
|
||||||
// What about data: and about:blank?
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Content scripts injection.
|
|
||||||
let lss = Services.scriptloader.loadSubScript;
|
|
||||||
let sandbox = this.initContentScripts(win, true);
|
|
||||||
try {
|
|
||||||
lss(this.contentBaseURI + 'vapi-client.js', sandbox);
|
|
||||||
lss(this.contentBaseURI + 'contentscript.js', sandbox);
|
|
||||||
} catch (ex) {
|
|
||||||
//console.exception(ex.msg, ex.stack);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// The remaining scripts are worth injecting only on a top-level window
|
|
||||||
// and at document_idle time.
|
|
||||||
if ( win === win.top ) {
|
|
||||||
this.injectOtherContentScripts(doc, sandbox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var processObserver = {
|
|
||||||
start: function() {
|
|
||||||
scriptTagFilterer.reset();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var LocationChangeListener = function(docShell, webProgress) {
|
|
||||||
var mm = docShell.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
|
||||||
if ( !mm || typeof mm.sendAsyncMessage !== 'function' ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.messageManager = mm;
|
|
||||||
webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION);
|
|
||||||
};
|
|
||||||
|
|
||||||
LocationChangeListener.prototype.messageName = hostName + ':locationChanged';
|
|
||||||
|
|
||||||
LocationChangeListener.prototype.QueryInterface = XPCOMUtils.generateQI([
|
|
||||||
'nsIWebProgressListener',
|
|
||||||
'nsISupportsWeakReference'
|
|
||||||
]);
|
|
||||||
|
|
||||||
LocationChangeListener.prototype.onLocationChange = function(webProgress, request, location, flags) {
|
|
||||||
if ( !webProgress.isTopLevel ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.messageManager.sendAsyncMessage(this.messageName, {
|
|
||||||
url: location.asciiSpec,
|
|
||||||
flags: flags
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
contentObserver.register();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1,62 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014-2016 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment
|
|
||||||
|
|
||||||
(function(context) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
if ( !context.docShell ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let webProgress = context.docShell
|
|
||||||
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
|
||||||
.getInterface(Components.interfaces.nsIWebProgress);
|
|
||||||
if ( !webProgress ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1514
|
|
||||||
// Fix?
|
|
||||||
let domWindow = webProgress.DOMWindow;
|
|
||||||
if ( domWindow !== domWindow.top ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let {LocationChangeListener} = Components.utils.import(
|
|
||||||
Components.stack.filename.replace('Script', 'Module'),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1444
|
|
||||||
// Apparently, on older versions of Firefox (31 and less), the same context
|
|
||||||
// is used for all frame scripts, hence we must use a unique variable name
|
|
||||||
// to ensure no collision.
|
|
||||||
context.ublock0LocationChangeListener = new LocationChangeListener(
|
|
||||||
context.docShell,
|
|
||||||
webProgress
|
|
||||||
);
|
|
||||||
})(this);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1,58 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014-2016 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment
|
|
||||||
|
|
||||||
(function(context) {
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
if ( !context.content ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let {contentObserver} = Components.utils.import(
|
|
||||||
Components.stack.filename.replace('Script0', 'Module'),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
let injectContentScripts = function(win) {
|
|
||||||
if ( !win || !win.document ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
contentObserver.observe(win.document);
|
|
||||||
|
|
||||||
if ( win.frames && win.frames.length ) {
|
|
||||||
let i = win.frames.length;
|
|
||||||
while ( i-- ) {
|
|
||||||
injectContentScripts(win.frames[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
injectContentScripts(context.content);
|
|
||||||
|
|
||||||
})(this);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1,6 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16px" width="16px">
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<path stroke-linejoin="round" d="M8,16c7-4,7-4,7-14-3,0-4,0-7-2m0,16c-7-4-7-4-7-14,3,0,4,0,7-2" fill-rule="nonzero" stroke="#FFF" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.12500024" fill="#808080"/>
|
|
||||||
<path style="color:#000000;" fill="#FFF" d="m9.5001,4.9981c-1.3748,0-2.5,1.1252-2.5,2.5s1.1252,2.5,2.5,2.5,2.5-1.1252,2.5-2.5-1.1252-2.5-2.5-2.5zm0,1c0.83435,0,1.5,0.66565,1.5,1.5s-0.66565,1.5-1.5,1.5-1.5-0.66565-1.5-1.5,0.66565-1.5,1.5-1.5z"/>
|
|
||||||
<path fill="#FFF" stroke-width="0" stroke-miterlimit="4" d="m7.9996,8.0002c0,1.375-0.625,2-2,2s-2-0.625-2-2v-2.9998h1.0001v3c0,0.875,0.125,1,1,1s1-0.125,1-1v-3h1z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 788 B |
|
@ -1,6 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16px" width="16px">
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<path stroke-linejoin="round" d="M8,16c7-4,7-4,7-14-3,0-4,0-7-2m0,16c-7-4-7-4-7-14,3,0,4,0,7-2" fill-rule="nonzero" stroke="#FFF" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.12500024" fill="#800000"/>
|
|
||||||
<path style="color:#000000;" fill="#FFF" d="m9.5001,4.9981c-1.3748,0-2.5,1.1252-2.5,2.5s1.1252,2.5,2.5,2.5,2.5-1.1252,2.5-2.5-1.1252-2.5-2.5-2.5zm0,1c0.83435,0,1.5,0.66565,1.5,1.5s-0.66565,1.5-1.5,1.5-1.5-0.66565-1.5-1.5,0.66565-1.5,1.5-1.5z"/>
|
|
||||||
<path fill="#FFF" stroke-width="0" stroke-miterlimit="4" d="m7.9996,8.0002c0,1.375-0.625,2-2,2s-2-0.625-2-2v-2.9998h1.0001v3c0,0.875,0.125,1,1,1s1-0.125,1-1v-3h1z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 788 B |
|
@ -1,6 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="24px" width="24px">
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<path stroke-linejoin="round" d="M8,16c7-4,7-4,7-14-3,0-4,0-7-2m0,16c-7-4-7-4-7-14,3,0,4,0,7-2" fill-rule="nonzero" stroke="#FFF" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.12500024" fill="#808080"/>
|
|
||||||
<path style="color:#000000;" fill="#FFF" d="m9.5001,4.9981c-1.3748,0-2.5,1.1252-2.5,2.5s1.1252,2.5,2.5,2.5,2.5-1.1252,2.5-2.5-1.1252-2.5-2.5-2.5zm0,1c0.83435,0,1.5,0.66565,1.5,1.5s-0.66565,1.5-1.5,1.5-1.5-0.66565-1.5-1.5,0.66565-1.5,1.5-1.5z"/>
|
|
||||||
<path fill="#FFF" stroke-width="0" stroke-miterlimit="4" d="m7.9996,8.0002c0,1.375-0.625,2-2,2s-2-0.625-2-2v-2.9998h1.0001v3c0,0.875,0.125,1,1,1s1-0.125,1-1v-3h1z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 788 B |
|
@ -1,6 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="24px" width="24px">
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
<path stroke-linejoin="round" d="M8,16c7-4,7-4,7-14-3,0-4,0-7-2m0,16c-7-4-7-4-7-14,3,0,4,0,7-2" fill-rule="nonzero" stroke="#FFF" stroke-linecap="round" stroke-miterlimit="4" stroke-width="0.12500024" fill="#800000"/>
|
|
||||||
<path style="color:#000000;" fill="#FFF" d="m9.5001,4.9981c-1.3748,0-2.5,1.1252-2.5,2.5s1.1252,2.5,2.5,2.5,2.5-1.1252,2.5-2.5-1.1252-2.5-2.5-2.5zm0,1c0.83435,0,1.5,0.66565,1.5,1.5s-0.66565,1.5-1.5,1.5-1.5-0.66565-1.5-1.5,0.66565-1.5,1.5-1.5z"/>
|
|
||||||
<path fill="#FFF" stroke-width="0" stroke-miterlimit="4" d="m7.9996,8.0002c0,1.375-0.625,2-2,2s-2-0.625-2-2v-2.9998h1.0001v3c0,0.875,0.125,1,1,1s1-0.125,1-1v-3h1z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 788 B |
|
@ -1,64 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
|
||||||
<Description about="urn:mozilla:install-manifest">
|
|
||||||
<em:id>uBlock0@raymondhill.net</em:id>
|
|
||||||
<em:version>{version}</em:version>
|
|
||||||
<em:name>{name}</em:name>
|
|
||||||
<em:description>{description}</em:description>
|
|
||||||
<em:homepageURL>{homepage}</em:homepageURL>
|
|
||||||
<em:creator>{author}</em:creator>
|
|
||||||
<em:developer>Deathamns</em:developer>
|
|
||||||
<em:developer>Alex Vallat</em:developer>
|
|
||||||
<em:developer>Manuel Reimer</em:developer>
|
|
||||||
<em:type>2</em:type>
|
|
||||||
<em:bootstrap>true</em:bootstrap>
|
|
||||||
<em:multiprocessCompatible>true</em:multiprocessCompatible>
|
|
||||||
<em:optionsType>2</em:optionsType>
|
|
||||||
{localized}
|
|
||||||
|
|
||||||
<!-- Firefox -->
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>{{ec8030f7-c20a-464f-9b0e-13a3a9e97384}}</em:id>
|
|
||||||
<em:minVersion>32.0</em:minVersion>
|
|
||||||
<em:maxVersion>56.0a1</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
|
|
||||||
<!-- Fennec -->
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>{{aa3c5121-dab2-40e2-81ca-7ea25febc110}}</em:id>
|
|
||||||
<em:minVersion>32.0</em:minVersion>
|
|
||||||
<em:maxVersion>56.0a1</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
|
|
||||||
<!-- SeaMonkey -->
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>{{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}}</em:id>
|
|
||||||
<em:minVersion>2.24</em:minVersion>
|
|
||||||
<em:maxVersion>*</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
|
|
||||||
<!-- Pale Moon -->
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>{{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}}</em:id>
|
|
||||||
<em:minVersion>27.0</em:minVersion>
|
|
||||||
<em:maxVersion>27.*</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
|
|
||||||
<!-- Thunderbird -->
|
|
||||||
<em:targetApplication>
|
|
||||||
<Description>
|
|
||||||
<em:id>{{3550f703-e582-4d05-9a08-453d09bdfdc6}}</em:id>
|
|
||||||
<em:minVersion>31.0</em:minVersion>
|
|
||||||
<em:maxVersion>45.*</em:maxVersion>
|
|
||||||
</Description>
|
|
||||||
</em:targetApplication>
|
|
||||||
</Description>
|
|
||||||
</RDF>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" ?>
|
|
||||||
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
<setting type="control">
|
|
||||||
<vbox>
|
|
||||||
<button id="showDashboardButton"/>
|
|
||||||
<button id="showNetworkLogButton"/>
|
|
||||||
</vbox>
|
|
||||||
</setting>
|
|
||||||
</vbox>
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2016-2017 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
// For background page or non-background pages
|
|
||||||
|
|
||||||
/* exported objectAssign */
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// As per MDN, Object.assign appeared first in Firefox 34.
|
|
||||||
// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility
|
|
||||||
|
|
||||||
var objectAssign = Object.assign || function(target, source) {
|
|
||||||
var keys = Object.keys(source);
|
|
||||||
for ( var i = 0, n = keys.length, key; i < n; i++ ) {
|
|
||||||
key = keys[i];
|
|
||||||
target[key] = source[key];
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2016 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIProcessScriptLoader
|
|
||||||
|
|
||||||
// Some module tasks need to run once per-content process. This is the purpose
|
|
||||||
// of this content process script.
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
let {processObserver} = Components.utils.import(
|
|
||||||
Components.stack.filename.replace('processScript.js', 'frameModule.js'),
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_loading_and_lifetime#Unloading_frame_scripts
|
|
||||||
// There is no way to unload a frame script, so when the extension will
|
|
||||||
// update, it may happen `processObserver` is not available because of
|
|
||||||
// trying to import from an older module version.
|
|
||||||
// TODO: remove the test once everybody is updated to 1.9.10+.
|
|
||||||
if ( processObserver ) {
|
|
||||||
processObserver.start();
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,399 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014-2017 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* global HTMLDocument, XMLDocument,
|
|
||||||
addMessageListener, removeMessageListener, sendAsyncMessage, outerShutdown
|
|
||||||
*/
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// For non background pages
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
(function(self) {
|
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://bugs.chromium.org/p/project-zero/issues/detail?id=1225&desc=6#c10
|
|
||||||
if ( !self.vAPI || self.vAPI.uBO !== true ) {
|
|
||||||
self.vAPI = { uBO: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
var vAPI = self.vAPI;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.firefox = true;
|
|
||||||
|
|
||||||
vAPI.randomToken = function() {
|
|
||||||
return String.fromCharCode(Date.now() % 26 + 97) +
|
|
||||||
Math.floor(Math.random() * 982451653 + 982451653).toString(36);
|
|
||||||
};
|
|
||||||
|
|
||||||
vAPI.sessionId = vAPI.randomToken();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.setTimeout = vAPI.setTimeout || function(callback, delay, extra) {
|
|
||||||
return setTimeout(function(a) { callback(a); }, delay, extra);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.shutdown = {
|
|
||||||
jobs: [],
|
|
||||||
add: function(job) {
|
|
||||||
this.jobs.push(job);
|
|
||||||
},
|
|
||||||
exec: function() {
|
|
||||||
var job;
|
|
||||||
while ( (job = this.jobs.pop()) ) {
|
|
||||||
job();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
remove: function(job) {
|
|
||||||
var pos;
|
|
||||||
while ( (pos = this.jobs.indexOf(job)) !== -1 ) {
|
|
||||||
this.jobs.splice(pos, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
if ( !self.getScriptTagFilters ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var hostname = location.hostname;
|
|
||||||
if ( !hostname ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var filters = self.getScriptTagFilters({
|
|
||||||
rootURL: self.location.href,
|
|
||||||
frameURL: self.location.href,
|
|
||||||
frameHostname: hostname
|
|
||||||
});
|
|
||||||
if ( typeof filters !== 'string' || filters === '' ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var reFilters = new RegExp(filters);
|
|
||||||
document.addEventListener('beforescriptexecute', function(ev) {
|
|
||||||
if ( reFilters.test(ev.target.textContent) ) {
|
|
||||||
ev.preventDefault();
|
|
||||||
ev.stopPropagation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var insertUserCSS = self.injectCSS || function(){},
|
|
||||||
removeUserCSS = self.removeCSS || function(){};
|
|
||||||
|
|
||||||
var processUserCSS = function(details, callback) {
|
|
||||||
var cssText;
|
|
||||||
var aa = details.add;
|
|
||||||
if ( Array.isArray(aa) ) {
|
|
||||||
for ( cssText of aa ) {
|
|
||||||
insertUserCSS(
|
|
||||||
'data:text/css;charset=utf-8,' +
|
|
||||||
encodeURIComponent(cssText)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aa = details.remove;
|
|
||||||
if ( Array.isArray(aa) ) {
|
|
||||||
for ( cssText of aa ) {
|
|
||||||
removeUserCSS(
|
|
||||||
'data:text/css;charset=utf-8,' +
|
|
||||||
encodeURIComponent(cssText)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( typeof callback === 'function' ) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.messaging = {
|
|
||||||
channels: new Map(),
|
|
||||||
pending: new Map(),
|
|
||||||
auxProcessId: 1,
|
|
||||||
connected: false,
|
|
||||||
|
|
||||||
messageListener: function(msg) {
|
|
||||||
var details = JSON.parse(msg);
|
|
||||||
if ( !details ) { return; }
|
|
||||||
|
|
||||||
// Sent to all channels
|
|
||||||
if ( details.broadcast && !details.channelName ) {
|
|
||||||
for ( var channelName of this.channels.keys() ) {
|
|
||||||
this.sendToChannelListeners(channelName, details.msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response to specific message previously sent
|
|
||||||
if ( details.auxProcessId ) {
|
|
||||||
var listener = this.pending.get(details.auxProcessId);
|
|
||||||
this.pending.delete(details.auxProcessId);
|
|
||||||
if ( listener ) {
|
|
||||||
listener(details.msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sent to a specific channel
|
|
||||||
this.sendToChannelListeners(details.channelName, details.msg);
|
|
||||||
},
|
|
||||||
|
|
||||||
builtinListener: function(msg) {
|
|
||||||
if ( msg.cmd === 'injectScript' ) {
|
|
||||||
// injectScript is not always present.
|
|
||||||
// - See contentObserver.initContentScripts in frameModule.js
|
|
||||||
if ( typeof self.injectScript !== 'function' ) { return; }
|
|
||||||
var details = msg.details;
|
|
||||||
// Whether to inject in all child frames. Default to only top frame.
|
|
||||||
var allFrames = details.allFrames || false;
|
|
||||||
if ( allFrames !== true && window !== window.top ) { return; }
|
|
||||||
// https://github.com/gorhill/uBlock/issues/876
|
|
||||||
// Enforce `details.runAt`. Default to `document_end`.
|
|
||||||
var runAt = details.runAt || 'document_end';
|
|
||||||
if ( runAt === 'document_start' || document.readyState !== 'loading' ) {
|
|
||||||
self.injectScript(details.file);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var injectScriptDelayed = function() {
|
|
||||||
document.removeEventListener('DOMContentLoaded', injectScriptDelayed);
|
|
||||||
self.injectScript(details.file);
|
|
||||||
};
|
|
||||||
document.addEventListener('DOMContentLoaded', injectScriptDelayed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( msg.cmd === 'shutdownSandbox' ) {
|
|
||||||
vAPI.shutdown.exec();
|
|
||||||
vAPI.messaging.stop();
|
|
||||||
if ( typeof self.outerShutdown === 'function' ) {
|
|
||||||
outerShutdown();
|
|
||||||
}
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1573
|
|
||||||
// Will let uBO's own web pages close themselves. `window.top` is
|
|
||||||
// used on the assumption that uBO's own web pages will never be
|
|
||||||
// embedded in anything else than its own documents.
|
|
||||||
try {
|
|
||||||
var top = window.top;
|
|
||||||
if ( top.location.href.startsWith(vAPI.getURL('')) ) {
|
|
||||||
top.close();
|
|
||||||
}
|
|
||||||
} catch (ex) {
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleListener: function({type, persisted}) {
|
|
||||||
if ( type === 'pagehide' && !persisted ) {
|
|
||||||
vAPI.shutdown.exec();
|
|
||||||
this.stop();
|
|
||||||
if ( typeof self.outerShutdown === 'function' ) {
|
|
||||||
outerShutdown();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( type === 'pagehide' ) {
|
|
||||||
this.disconnect();
|
|
||||||
} else /* if ( type === 'pageshow' ) */ {
|
|
||||||
this.connect();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggleListenerCallback: null,
|
|
||||||
|
|
||||||
start: function() {
|
|
||||||
this.addChannelListener('vAPI', this.builtinListener);
|
|
||||||
if ( this.toggleListenerCallback === null ) {
|
|
||||||
this.toggleListenerCallback = this.toggleListener.bind(this);
|
|
||||||
}
|
|
||||||
window.addEventListener('pagehide', this.toggleListenerCallback, true);
|
|
||||||
window.addEventListener('pageshow', this.toggleListenerCallback, true);
|
|
||||||
},
|
|
||||||
|
|
||||||
stop: function() {
|
|
||||||
if ( this.toggleListenerCallback !== null ) {
|
|
||||||
window.removeEventListener('pagehide', this.toggleListenerCallback, true);
|
|
||||||
window.removeEventListener('pageshow', this.toggleListenerCallback, true);
|
|
||||||
}
|
|
||||||
this.disconnect();
|
|
||||||
this.channels.clear();
|
|
||||||
// service pending callbacks
|
|
||||||
var pending = this.pending;
|
|
||||||
this.pending = new Map();
|
|
||||||
for ( var callback of pending.values() ) {
|
|
||||||
if ( typeof callback === 'function' ) {
|
|
||||||
callback(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
connect: function() {
|
|
||||||
if ( !this.connected ) {
|
|
||||||
addMessageListener(this.messageListener.bind(this));
|
|
||||||
this.connected = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
disconnect: function() {
|
|
||||||
if ( this.connected ) {
|
|
||||||
removeMessageListener();
|
|
||||||
this.connected = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
send: function(channelName, message, callback) {
|
|
||||||
// User stylesheets are handled content-side on legacy Firefox.
|
|
||||||
if ( channelName === 'vapi' && message.what === 'userCSS' ) {
|
|
||||||
return processUserCSS(message, callback);
|
|
||||||
}
|
|
||||||
if ( !this.connected ) {
|
|
||||||
if ( typeof callback === 'function' ) { callback(); }
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Too large a gap between the last request and the last response means
|
|
||||||
// the main process is no longer reachable: memory leaks and bad
|
|
||||||
// performance become a risk -- especially for long-lived, dynamic
|
|
||||||
// pages. Guard against this.
|
|
||||||
if ( this.pending.size > 25 ) {
|
|
||||||
vAPI.shutdown.exec();
|
|
||||||
}
|
|
||||||
this.connect();
|
|
||||||
var auxProcessId;
|
|
||||||
if ( callback ) {
|
|
||||||
auxProcessId = this.auxProcessId++;
|
|
||||||
this.pending.set(auxProcessId, callback);
|
|
||||||
}
|
|
||||||
sendAsyncMessage('ublock0:background', {
|
|
||||||
channelName: self._sandboxId_ + '|' + channelName,
|
|
||||||
auxProcessId: auxProcessId,
|
|
||||||
msg: message
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO: implement as time permits.
|
|
||||||
connectTo: function(from, to, handler) {
|
|
||||||
handler({
|
|
||||||
what: 'connectionRefused',
|
|
||||||
from: from,
|
|
||||||
to: to
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
disconnectFrom: function() {
|
|
||||||
},
|
|
||||||
|
|
||||||
sendTo: function() {
|
|
||||||
},
|
|
||||||
|
|
||||||
addChannelListener: function(channelName, listener) {
|
|
||||||
var listeners = this.channels.get(channelName);
|
|
||||||
if ( listeners === undefined ) {
|
|
||||||
this.channels.set(channelName, [ listener ]);
|
|
||||||
} else if ( listeners.indexOf(listener) === -1 ) {
|
|
||||||
listeners.push(listener);
|
|
||||||
}
|
|
||||||
this.connect();
|
|
||||||
},
|
|
||||||
|
|
||||||
removeChannelListener: function(channelName, listener) {
|
|
||||||
var listeners = this.channels.get(channelName);
|
|
||||||
if ( listeners === undefined ) { return; }
|
|
||||||
var pos = listeners.indexOf(listener);
|
|
||||||
if ( pos === -1 ) { return; }
|
|
||||||
listeners.splice(pos, 1);
|
|
||||||
if ( listeners.length === 0 ) {
|
|
||||||
this.channels.delete(channelName);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
removeAllChannelListeners: function(channelName) {
|
|
||||||
this.channels.delete(channelName);
|
|
||||||
},
|
|
||||||
|
|
||||||
sendToChannelListeners: function(channelName, msg) {
|
|
||||||
var listeners = this.channels.get(channelName);
|
|
||||||
if ( listeners === undefined ) { return; }
|
|
||||||
listeners = listeners.slice(0);
|
|
||||||
var response;
|
|
||||||
for ( var listener of listeners ) {
|
|
||||||
response = listener(msg);
|
|
||||||
if ( response !== undefined ) { break; }
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
vAPI.messaging.start();
|
|
||||||
|
|
||||||
// https://www.youtube.com/watch?v=Cg0cmhjdiLs
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=444165
|
|
||||||
// https://github.com/gorhill/uBlock/issues/2256
|
|
||||||
// Not the prettiest solution, but that's the safest/simplest I can think
|
|
||||||
// of at this point. If/when bugzilla issue above is solved, we will need
|
|
||||||
// version detection to decide whether the patch needs to be applied.
|
|
||||||
|
|
||||||
vAPI.iframeLoadEventPatch = function(target) {
|
|
||||||
if ( target.localName === 'iframe' ) {
|
|
||||||
target.dispatchEvent(new Event('load'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// No need to have vAPI client linger around after shutdown if
|
|
||||||
// we are not a top window (because element picker can still
|
|
||||||
// be injected in top window).
|
|
||||||
if ( window !== window.top ) {
|
|
||||||
// Can anything be done?
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
})(this);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1,167 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
|
|
||||||
uBlock Origin - a browser extension to block requests.
|
|
||||||
Copyright (C) 2014-2017 The uBlock Origin authors
|
|
||||||
|
|
||||||
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/}.
|
|
||||||
|
|
||||||
Home: https://github.com/gorhill/uBlock
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* global sendAsyncMessage */
|
|
||||||
|
|
||||||
// For background page or non-background pages
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
(function(self) {
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
const {Services} = Components.utils.import(
|
|
||||||
'resource://gre/modules/Services.jsm',
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// https://bugs.chromium.org/p/project-zero/issues/detail?id=1225&desc=6#c10
|
|
||||||
if ( !self.vAPI || self.vAPI.uBO !== true ) {
|
|
||||||
self.vAPI = { uBO: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
var vAPI = self.vAPI;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.setTimeout = vAPI.setTimeout || function(callback, delay, extra) {
|
|
||||||
return setTimeout(function(a) { callback(a); }, delay, extra);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// http://www.w3.org/International/questions/qa-scripts#directions
|
|
||||||
|
|
||||||
var setScriptDirection = function(language) {
|
|
||||||
document.body.setAttribute(
|
|
||||||
'dir',
|
|
||||||
['ar', 'he', 'fa', 'ps', 'ur'].indexOf(language) !== -1 ? 'rtl' : 'ltr'
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.download = function(details) {
|
|
||||||
if ( !details.url ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var a = document.createElement('a');
|
|
||||||
a.href = details.url;
|
|
||||||
a.setAttribute('download', details.filename || '');
|
|
||||||
a.dispatchEvent(new MouseEvent('click'));
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.getURL = function(path) {
|
|
||||||
return 'chrome://' + location.host + '/content/' + path.replace(/^\/+/, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.i18n = (function() {
|
|
||||||
var stringBundle = Services.strings.createBundle(
|
|
||||||
'chrome://' + location.host + '/locale/messages.properties'
|
|
||||||
);
|
|
||||||
|
|
||||||
return function(s) {
|
|
||||||
try {
|
|
||||||
return stringBundle.GetStringFromName(s);
|
|
||||||
} catch (ex) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
setScriptDirection(navigator.language);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.closePopup = function() {
|
|
||||||
sendAsyncMessage(location.host + ':closePopup');
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// A localStorage-like object which should be accessible from the
|
|
||||||
// background page or auxiliary pages.
|
|
||||||
// This storage is optional, but it is nice to have, for a more polished user
|
|
||||||
// experience.
|
|
||||||
|
|
||||||
vAPI.localStorage = {
|
|
||||||
pbName: '',
|
|
||||||
pb: null,
|
|
||||||
str: Components.classes['@mozilla.org/supports-string;1']
|
|
||||||
.createInstance(Components.interfaces.nsISupportsString),
|
|
||||||
init: function(pbName) {
|
|
||||||
this.pbName = pbName;
|
|
||||||
this.pb = Services.prefs.getBranch(pbName);
|
|
||||||
},
|
|
||||||
getItem: function(key) {
|
|
||||||
try {
|
|
||||||
return this.pb.getComplexValue(
|
|
||||||
key,
|
|
||||||
Components.interfaces.nsISupportsString
|
|
||||||
).data;
|
|
||||||
} catch (ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setItem: function(key, value) {
|
|
||||||
this.str.data = value;
|
|
||||||
this.pb.setComplexValue(
|
|
||||||
key,
|
|
||||||
Components.interfaces.nsISupportsString,
|
|
||||||
this.str
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getBool: function(key) {
|
|
||||||
try {
|
|
||||||
return this.pb.getBoolPref(key);
|
|
||||||
} catch (ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setBool: function(key, value) {
|
|
||||||
this.pb.setBoolPref(key, value);
|
|
||||||
},
|
|
||||||
setDefaultBool: function(key, defaultValue) {
|
|
||||||
Services.prefs.getDefaultBranch(this.pbName).setBoolPref(key, defaultValue);
|
|
||||||
},
|
|
||||||
removeItem: function(key) {
|
|
||||||
this.pb.clearUserPref(key);
|
|
||||||
},
|
|
||||||
clear: function() {
|
|
||||||
this.pb.deleteBranch('');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
vAPI.localStorage.init('extensions.' + location.host + '.');
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
})(this);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
|
@ -1,122 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
import json
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
from io import open
|
|
||||||
from shutil import rmtree
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
if len(sys.argv) == 1 or not sys.argv[1]:
|
|
||||||
raise SystemExit('Build dir missing.')
|
|
||||||
|
|
||||||
|
|
||||||
def mkdirs(path):
|
|
||||||
try:
|
|
||||||
os.makedirs(path)
|
|
||||||
finally:
|
|
||||||
return os.path.exists(path)
|
|
||||||
|
|
||||||
pj = os.path.join
|
|
||||||
|
|
||||||
# Find path to project root
|
|
||||||
proj_dir = os.path.split(os.path.abspath(__file__))[0]
|
|
||||||
while not os.path.isdir(os.path.join(proj_dir, '.git')):
|
|
||||||
proj_dir = os.path.normpath(os.path.join(proj_dir, '..'))
|
|
||||||
|
|
||||||
# Check that found project root is valid
|
|
||||||
version_filepath = os.path.join(proj_dir, 'dist', 'version')
|
|
||||||
if not os.path.isfile(version_filepath):
|
|
||||||
print('Version file not found.')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
build_dir = os.path.abspath(sys.argv[1])
|
|
||||||
source_locale_dir = pj(build_dir, '_locales')
|
|
||||||
target_locale_dir = pj(build_dir, 'locale')
|
|
||||||
language_codes = []
|
|
||||||
descriptions = OrderedDict({})
|
|
||||||
title_case_strings = ['pickerContextMenuEntry', 'contextMenuTemporarilyAllowLargeMediaElements']
|
|
||||||
|
|
||||||
for alpha2 in sorted(os.listdir(source_locale_dir)):
|
|
||||||
locale_path = pj(source_locale_dir, alpha2, 'messages.json')
|
|
||||||
with open(locale_path, encoding='utf-8') as f:
|
|
||||||
strings = json.load(f, object_pairs_hook=OrderedDict)
|
|
||||||
alpha2 = alpha2.replace('_', '-')
|
|
||||||
descriptions[alpha2] = strings['extShortDesc']['message']
|
|
||||||
del strings['extShortDesc']
|
|
||||||
language_codes.append(alpha2)
|
|
||||||
mkdirs(pj(target_locale_dir, alpha2))
|
|
||||||
locale_path = pj(target_locale_dir, alpha2, 'messages.properties')
|
|
||||||
with open(locale_path, 'wt', encoding='utf-8', newline='\n') as f:
|
|
||||||
for string_name in strings:
|
|
||||||
string = strings[string_name]['message']
|
|
||||||
if alpha2 == 'en' and string_name in title_case_strings:
|
|
||||||
string = string.title()
|
|
||||||
f.write(string_name)
|
|
||||||
f.write(u'=')
|
|
||||||
f.write(string.replace('\n', r'\n'))
|
|
||||||
f.write(u'\n')
|
|
||||||
|
|
||||||
# generate chrome.manifest file
|
|
||||||
chrome_manifest = pj(build_dir, 'chrome.manifest')
|
|
||||||
|
|
||||||
with open(chrome_manifest, 'at', encoding='utf-8', newline='\n') as f:
|
|
||||||
f.write(u'\nlocale ublock0 en ./locale/en/\n')
|
|
||||||
for alpha2 in language_codes:
|
|
||||||
if alpha2 == 'en':
|
|
||||||
continue
|
|
||||||
f.write(u'locale ublock0 ' + alpha2 + ' ./locale/' + alpha2 + '/\n')
|
|
||||||
|
|
||||||
rmtree(source_locale_dir)
|
|
||||||
|
|
||||||
# update install.rdf
|
|
||||||
|
|
||||||
chromium_manifest = pj(proj_dir, 'platform', 'chromium', 'manifest.json')
|
|
||||||
with open(chromium_manifest, encoding='utf-8') as m:
|
|
||||||
manifest = json.load(m)
|
|
||||||
|
|
||||||
# Fetch extension version
|
|
||||||
# https://developer.mozilla.org/en-US/Add-ons/AMO/Policy/Maintenance#How_do_I_submit_a_Beta_add-on.3F
|
|
||||||
# "To create a beta channel [...] '(a|alpha|b|beta|pre|rc)\d*$' "
|
|
||||||
|
|
||||||
version = ''
|
|
||||||
with open(version_filepath) as f:
|
|
||||||
version = f.read().strip()
|
|
||||||
match = re.search('^(\d+\.\d+\.\d+)(\.\d+)$', version)
|
|
||||||
if match:
|
|
||||||
buildtype = int(match.group(2)[1:])
|
|
||||||
if buildtype < 100:
|
|
||||||
builttype = 'b' + str(buildtype)
|
|
||||||
else:
|
|
||||||
builttype = 'rc' + str(buildtype - 100)
|
|
||||||
version = match.group(1) + builttype
|
|
||||||
manifest['version'] = version
|
|
||||||
|
|
||||||
manifest['homepage'] = 'https://github.com/gorhill/uBlock'
|
|
||||||
manifest['description'] = descriptions['en']
|
|
||||||
del descriptions['en']
|
|
||||||
|
|
||||||
manifest['localized'] = []
|
|
||||||
t = ' '
|
|
||||||
t3 = 3 * t
|
|
||||||
for alpha2 in descriptions:
|
|
||||||
if alpha2 == 'en':
|
|
||||||
continue
|
|
||||||
manifest['localized'].append(
|
|
||||||
'\n' + t*2 + '<em:localized><Description>\n' +
|
|
||||||
t3 + '<em:locale>' + alpha2 + '</em:locale>\n' +
|
|
||||||
t3 + '<em:name>' + manifest['name'] + '</em:name>\n' +
|
|
||||||
t3 + '<em:description>' + descriptions[alpha2] + '</em:description>\n' +
|
|
||||||
t3 + '<em:creator>' + manifest['author'] + '</em:creator>\n' +
|
|
||||||
# t3 + '<translator>' + ??? + '</translator>\n' +
|
|
||||||
t3 + '<em:homepageURL>' + manifest['homepage'] + '</em:homepageURL>\n' +
|
|
||||||
t*2 + '</Description></em:localized>'
|
|
||||||
)
|
|
||||||
manifest['localized'] = '\n'.join(manifest['localized'])
|
|
||||||
|
|
||||||
install_rdf = pj(build_dir, 'install.rdf')
|
|
||||||
with open(install_rdf, 'r+t', encoding='utf-8', newline='\n') as f:
|
|
||||||
install_rdf = f.read()
|
|
||||||
f.seek(0)
|
|
||||||
f.write(install_rdf.format(**manifest))
|
|
|
@ -1,56 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
#
|
|
||||||
# This script assumes a linux environment
|
|
||||||
|
|
||||||
echo "*** uBlock0.firefox: Copying files"
|
|
||||||
|
|
||||||
DES=dist/build/uBlock0.firefox
|
|
||||||
rm -rf $DES
|
|
||||||
mkdir -p $DES
|
|
||||||
|
|
||||||
bash ./tools/make-assets.sh $DES
|
|
||||||
|
|
||||||
cp -R src/css $DES/
|
|
||||||
cp -R src/img $DES/
|
|
||||||
cp -R src/js $DES/
|
|
||||||
cp -R src/lib $DES/
|
|
||||||
cp -R src/_locales $DES/
|
|
||||||
cp src/*.html $DES/
|
|
||||||
|
|
||||||
mv $DES/img/icon_128.png $DES/icon.png
|
|
||||||
cp platform/firefox/css/* $DES/css/
|
|
||||||
cp platform/firefox/polyfill.js $DES/js/
|
|
||||||
cp platform/firefox/vapi-*.js $DES/js/
|
|
||||||
cp platform/chromium/vapi-usercss.real.js $DES/js/
|
|
||||||
cp platform/webext/vapi-usercss.js $DES/js/
|
|
||||||
cp platform/firefox/bootstrap.js $DES/
|
|
||||||
cp platform/firefox/processScript.js $DES/
|
|
||||||
cp platform/firefox/frame*.js $DES/
|
|
||||||
cp -R platform/firefox/img $DES/
|
|
||||||
cp platform/firefox/chrome.manifest $DES/
|
|
||||||
cp platform/firefox/install.rdf $DES/
|
|
||||||
cp platform/firefox/*.xul $DES/
|
|
||||||
cp LICENSE.txt $DES/
|
|
||||||
|
|
||||||
echo "*** uBlock0.firefox: concatenating content scripts"
|
|
||||||
cat $DES/js/vapi-usercss.js > /tmp/contentscript.js
|
|
||||||
echo >> /tmp/contentscript.js
|
|
||||||
grep -v "^'use strict';$" $DES/js/vapi-usercss.real.js >> /tmp/contentscript.js
|
|
||||||
echo >> /tmp/contentscript.js
|
|
||||||
grep -v "^'use strict';$" $DES/js/contentscript.js >> /tmp/contentscript.js
|
|
||||||
mv /tmp/contentscript.js $DES/js/contentscript.js
|
|
||||||
rm $DES/js/vapi-usercss.js
|
|
||||||
rm $DES/js/vapi-usercss.real.js
|
|
||||||
|
|
||||||
echo "*** uBlock0.firefox: Generating meta..."
|
|
||||||
python tools/make-firefox-meta.py $DES/
|
|
||||||
|
|
||||||
if [ "$1" = all ]; then
|
|
||||||
set +v
|
|
||||||
echo "*** uBlock0.firefox: Creating package..."
|
|
||||||
pushd $DES/ > /dev/null
|
|
||||||
zip ../uBlock0.firefox.xpi -qr *
|
|
||||||
popd > /dev/null
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "*** uBlock0.firefox: Package done."
|
|
Loading…
Reference in a new issue