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