Raymond Hill
6 years ago
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
16 changed files with 0 additions and 4913 deletions
-
245platform/firefox/bootstrap.js
-
1platform/firefox/chrome.manifest
-
46platform/firefox/css/legacy-toolbar-button.css
-
356platform/firefox/frameModule.js
-
72platform/firefox/frameScript.js
-
BINplatform/firefox/img/browsericons/icon19-19.png
-
BINplatform/firefox/img/browsericons/icon19-off.png
-
45platform/firefox/install.rdf
-
9platform/firefox/options.xul
-
95platform/firefox/polyfill.js
-
3465platform/firefox/vapi-background.js
-
225platform/firefox/vapi-client.js
-
191platform/firefox/vapi-common.js
-
1platform/firefox/vapi-popup.js
-
120tools/make-firefox-meta.py
-
42tools/make-firefox.sh
@ -1,245 +0,0 @@ |
|||||
/******************************************************************************* |
|
||||
|
|
||||
uMatrix - a browser extension to block requests. |
|
||||
Copyright (C) 2014-2017 The uMatrix/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/uMatrix
|
|
||||
*/ |
|
||||
|
|
||||
/* 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*=umatrix]').contentWindow;
|
|
||||
|
|
||||
let windowlessBrowser = null; |
|
||||
let windowlessBrowserPL = null; |
|
||||
let bgProcess = null; |
|
||||
let version; |
|
||||
const hostName = 'umatrix'; |
|
||||
const restartListener = { |
|
||||
get messageManager() { |
|
||||
return Cc['@mozilla.org/parentprocessmessagemanager;1'] |
|
||||
.getService(Ci.nsIMessageListenerManager); |
|
||||
}, |
|
||||
|
|
||||
receiveMessage: function() { |
|
||||
shutdown(); |
|
||||
startup(); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
// https://github.com/gorhill/uBlock/issues/2493
|
|
||||
// Fix by https://github.com/gijsk
|
|
||||
// imported from https://github.com/gorhill/uBlock/pull/2497
|
|
||||
|
|
||||
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() { |
|
||||
// https://bugzil.la/719376
|
|
||||
Cc['@mozilla.org/intl/stringbundle;1'] |
|
||||
.getService(Ci.nsIStringBundleService) |
|
||||
.flushBundles(); |
|
||||
} |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
function uninstall(data, aReason) { |
|
||||
if ( aReason !== ADDON_UNINSTALL ) { |
|
||||
return; |
|
||||
} |
|
||||
// To cleanup vAPI.localStorage in vapi-common.js, aka
|
|
||||
// "extensions.umatrix.*" in `about:config`.
|
|
||||
Cu.import('resource://gre/modules/Services.jsm', null) |
|
||||
.Services.prefs.getBranch('extensions.' + hostName + '.') |
|
||||
.deleteBranch(''); |
|
||||
} |
|
||||
|
|
||||
/******************************************************************************/ |
|
@ -1 +0,0 @@ |
|||||
content umatrix ./ |
|
@ -1,46 +0,0 @@ |
|||||
#umatrix-legacy-button { |
|
||||
list-style-image: url('../img/browsericons/icon19-19.png'); |
|
||||
} |
|
||||
#umatrix-legacy-button.off { |
|
||||
list-style-image: url('../img/browsericons/icon19-off.png'); |
|
||||
} |
|
||||
|
|
||||
toolbar[iconsize="small"] #umatrix-legacy-button { |
|
||||
list-style-image: url('../img/browsericons/icon19-19.png'); |
|
||||
} |
|
||||
toolbar[iconsize="small"] #umatrix-legacy-button.off { |
|
||||
list-style-image: url('../img/browsericons/icon19-off.png'); |
|
||||
} |
|
||||
#umatrix-legacy-button[badge]::before { |
|
||||
background: #000; |
|
||||
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. |
|
||||
**/ |
|
||||
#umatrix-legacy-button[badge=""]::before { |
|
||||
padding: 0; |
|
||||
} |
|
||||
|
|
||||
/* Override off state when in palette */ |
|
||||
toolbarpaletteitem #umatrix-legacy-button.off { |
|
||||
list-style-image: url('../img/browsericons/icon19-12.png'); |
|
||||
} |
|
||||
|
|
||||
/* Override badge when in palette */ |
|
||||
toolbarpaletteitem #umatrix-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 */ |
|
||||
#umatrix-legacy-button .toolbarbutton-menu-dropmarker { |
|
||||
display: none; |
|
||||
-moz-box-orient: horizontal; |
|
||||
} |
|
@ -1,356 +0,0 @@ |
|||||
/******************************************************************************* |
|
||||
|
|
||||
µBlock - a browser extension to block requests. |
|
||||
Copyright (C) 2014 The µBlock 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/uMatrix
|
|
||||
*/ |
|
||||
|
|
||||
/* global Components */ |
|
||||
|
|
||||
'use strict'; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
// https://github.com/gorhill/uBlock/issues/800#issuecomment-146580443
|
|
||||
this.EXPORTED_SYMBOLS = ['contentObserver', '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; |
|
||||
|
|
||||
// Cu.import('resource://gre/modules/Console.jsm');
|
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
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; |
|
||||
}; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
var contentObserver = { |
|
||||
classDescription: 'content-policy for ' + hostName, |
|
||||
classID: Components.ID('{c84283d4-9975-41b7-b1a4-f106af56b51d}'), |
|
||||
contractID: '@' + hostName + '/content-policy;1', |
|
||||
ACCEPT: Ci.nsIContentPolicy.ACCEPT, |
|
||||
MAIN_FRAME: Ci.nsIContentPolicy.TYPE_DOCUMENT, |
|
||||
contentBaseURI: 'chrome://' + hostName + '/content/js/', |
|
||||
cpMessageName: hostName + ':shouldLoad', |
|
||||
uniqueSandboxId: 1, |
|
||||
modernFirefox: |
|
||||
Services.vc.compare(Services.appinfo.platformVersion, '44') > 0 && ( |
|
||||
Services.appinfo.ID === '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}' || |
|
||||
Services.appinfo.ID === '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}' |
|
||||
), |
|
||||
|
|
||||
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); |
|
||||
|
|
||||
if ( !this.modernFirefox ) { |
|
||||
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'); |
|
||||
|
|
||||
if ( !this.modernFirefox ) { |
|
||||
this.componentRegistrar.unregisterFactory( |
|
||||
this.classID, |
|
||||
this |
|
||||
); |
|
||||
this.categoryManager.deleteCategoryEntry( |
|
||||
'content-policy', |
|
||||
this.contractID, |
|
||||
false |
|
||||
); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIContentPolicy
|
|
||||
// https://bugzil.la/612921
|
|
||||
shouldLoad: function(type, location, origin, context) { |
|
||||
if ( Services === undefined || !context ) { |
|
||||
return this.ACCEPT; |
|
||||
} |
|
||||
|
|
||||
if ( !location.schemeIs('http') && !location.schemeIs('https') ) { |
|
||||
return this.ACCEPT; |
|
||||
} |
|
||||
|
|
||||
var contextWindow; |
|
||||
if ( type === this.MAIN_FRAME ) { |
|
||||
contextWindow = context.contentWindow || context; |
|
||||
} else if ( type === this.SUB_FRAME ) { |
|
||||
contextWindow = context.contentWindow; |
|
||||
} else { |
|
||||
contextWindow = (context.ownerDocument || context).defaultView; |
|
||||
} |
|
||||
|
|
||||
// https://github.com/gorhill/uMatrix/issues/706
|
|
||||
if ( !contextWindow ) { |
|
||||
return this.ACCEPT; |
|
||||
} |
|
||||
|
|
||||
// The context for the toolbar popup is an iframe element here,
|
|
||||
// so check context.top instead of context
|
|
||||
if ( !contextWindow.top || !contextWindow.location ) { |
|
||||
return this.ACCEPT; |
|
||||
} |
|
||||
|
|
||||
let messageManager = getMessageManager(contextWindow); |
|
||||
if ( messageManager === null ) { |
|
||||
return this.ACCEPT; |
|
||||
} |
|
||||
|
|
||||
let details = { |
|
||||
rawType: type, |
|
||||
url: location.asciiSpec |
|
||||
}; |
|
||||
|
|
||||
if ( typeof messageManager.sendRpcMessage === 'function' ) { |
|
||||
// https://bugzil.la/1092216
|
|
||||
messageManager.sendRpcMessage(this.cpMessageName, details); |
|
||||
} else { |
|
||||
// Compatibility for older versions
|
|
||||
messageManager.sendSyncMessage(this.cpMessageName, details); |
|
||||
} |
|
||||
|
|
||||
return this.ACCEPT; |
|
||||
}, |
|
||||
|
|
||||
initContentScripts: function(win, sandbox) { |
|
||||
let messager = getMessageManager(win); |
|
||||
let sandboxId = hostName + ':sb:' + this.uniqueSandboxId++; |
|
||||
|
|
||||
if ( sandbox ) { |
|
||||
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.injectScript = function(script) { |
|
||||
Services.scriptloader.loadSubScript(script, sandbox); |
|
||||
}; |
|
||||
} |
|
||||
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); |
|
||||
}; |
|
||||
|
|
||||
messager.addMessageListener( |
|
||||
sandbox._sandboxId_, |
|
||||
sandbox._messageListener_ |
|
||||
); |
|
||||
messager.addMessageListener( |
|
||||
hostName + ':broadcast', |
|
||||
sandbox._messageListener_ |
|
||||
); |
|
||||
}; |
|
||||
|
|
||||
sandbox.removeMessageListener = function() { |
|
||||
try { |
|
||||
messager.removeMessageListener( |
|
||||
sandbox._sandboxId_, |
|
||||
sandbox._messageListener_ |
|
||||
); |
|
||||
messager.removeMessageListener( |
|
||||
hostName + ':broadcast', |
|
||||
sandbox._messageListener_ |
|
||||
); |
|
||||
} catch (ex) { |
|
||||
// It throws sometimes, mostly when the popup closes
|
|
||||
} |
|
||||
|
|
||||
sandbox._messageListener_ = null; |
|
||||
}; |
|
||||
|
|
||||
return sandbox; |
|
||||
}, |
|
||||
|
|
||||
observe: function(doc) { |
|
||||
let win = doc.defaultView; |
|
||||
if ( !win ) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
let loc = win.location; |
|
||||
if ( !loc ) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// https://github.com/gorhill/uBlock/issues/260
|
|
||||
// TODO: We may have to skip more types, for now let's be
|
|
||||
// conservative, i.e. let's not test against `text/html`.
|
|
||||
if ( doc.contentType.lastIndexOf('image/', 0) === 0 ) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if ( loc.protocol !== 'http:' && loc.protocol !== 'https:' && loc.protocol !== 'file:' ) { |
|
||||
if ( loc.protocol === 'chrome:' && loc.host === hostName ) { |
|
||||
this.initContentScripts(win); |
|
||||
} |
|
||||
|
|
||||
// What about data: and about:blank?
|
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
let lss = Services.scriptloader.loadSubScript; |
|
||||
let sandbox = this.initContentScripts(win, true); |
|
||||
|
|
||||
// Can throw with attempts at injecting into non-HTML document.
|
|
||||
// Example: https://a.pomf.se/avonjf.webm
|
|
||||
try { |
|
||||
lss(this.contentBaseURI + 'vapi-client.js', sandbox); |
|
||||
lss(this.contentBaseURI + 'contentscript-start.js', sandbox); |
|
||||
} catch (ex) { |
|
||||
return; // don't further try to inject anything
|
|
||||
} |
|
||||
|
|
||||
let docReady = (e) => { |
|
||||
let doc = e.target; |
|
||||
doc.removeEventListener(e.type, docReady, true); |
|
||||
lss(this.contentBaseURI + 'contentscript-end.js', sandbox); |
|
||||
}; |
|
||||
|
|
||||
if ( doc.readyState === 'loading') { |
|
||||
doc.addEventListener('DOMContentLoaded', docReady, true); |
|
||||
} else { |
|
||||
docReady({ target: doc, type: 'DOMContentLoaded' }); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
const locationChangedMessageName = hostName + ':locationChanged'; |
|
||||
|
|
||||
var LocationChangeListener = function(docShell) { |
|
||||
if ( !docShell ) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var requestor = docShell.QueryInterface(Ci.nsIInterfaceRequestor); |
|
||||
var ds = requestor.getInterface(Ci.nsIWebProgress); |
|
||||
var mm = requestor.getInterface(Ci.nsIContentFrameMessageManager); |
|
||||
|
|
||||
if ( ds && mm && typeof mm.sendAsyncMessage === 'function' ) { |
|
||||
this.docShell = ds; |
|
||||
this.messageManager = mm; |
|
||||
ds.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_LOCATION); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
LocationChangeListener.prototype.QueryInterface = XPCOMUtils.generateQI([ |
|
||||
'nsIWebProgressListener', |
|
||||
'nsISupportsWeakReference' |
|
||||
]); |
|
||||
|
|
||||
LocationChangeListener.prototype.onLocationChange = function(webProgress, request, location, flags) { |
|
||||
if ( !webProgress.isTopLevel ) { |
|
||||
return; |
|
||||
} |
|
||||
this.messageManager.sendAsyncMessage(locationChangedMessageName, { |
|
||||
url: location.asciiSpec, |
|
||||
flags: flags, |
|
||||
}); |
|
||||
}; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
contentObserver.register(); |
|
||||
|
|
||||
/******************************************************************************/ |
|
@ -1,72 +0,0 @@ |
|||||
/******************************************************************************* |
|
||||
|
|
||||
µBlock - a browser extension to block requests. |
|
||||
Copyright (C) 2014 The µBlock 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/uMatrix
|
|
||||
*/ |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
var locationChangeListener; // Keep alive while frameScript is alive
|
|
||||
|
|
||||
(function() { |
|
||||
|
|
||||
'use strict'; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
let {contentObserver, LocationChangeListener} = Components.utils.import( |
|
||||
Components.stack.filename.replace('Script', '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]); |
|
||||
} |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
let onLoadCompleted = function() { |
|
||||
removeMessageListener('umatrix-load-completed', onLoadCompleted); |
|
||||
injectContentScripts(content); |
|
||||
}; |
|
||||
|
|
||||
addMessageListener('umatrix-load-completed', onLoadCompleted); |
|
||||
|
|
||||
if ( docShell ) { |
|
||||
let Ci = Components.interfaces; |
|
||||
let wp = docShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebProgress); |
|
||||
let dw = wp.DOMWindow; |
|
||||
if ( dw === dw.top ) { |
|
||||
locationChangeListener = new LocationChangeListener(docShell); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
})(); |
|
||||
|
|
||||
/******************************************************************************/ |
|
Before Width: 19 | Height: 19 | Size: 750 B |
Before Width: 19 | Height: 19 | Size: 777 B |
@ -1,45 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<r:RDF xmlns:r="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.mozilla.org/2004/em-rdf#"> |
|
||||
<r:Description about="urn:mozilla:install-manifest"> |
|
||||
<id>uMatrix@raymondhill.net</id> |
|
||||
<version>{version}</version> |
|
||||
<name>{name}</name> |
|
||||
<description>{description}</description> |
|
||||
<homepageURL>{homepage}</homepageURL> |
|
||||
<creator>{author}</creator> |
|
||||
<developer>Deathamns</developer> |
|
||||
<developer>Alex Vallat</developer> |
|
||||
<type>2</type> |
|
||||
<bootstrap>true</bootstrap> |
|
||||
<multiprocessCompatible>true</multiprocessCompatible> |
|
||||
<optionsType>2</optionsType> |
|
||||
{localized} |
|
||||
|
|
||||
<!-- Firefox --> |
|
||||
<targetApplication> |
|
||||
<r:Description> |
|
||||
<id>{{ec8030f7-c20a-464f-9b0e-13a3a9e97384}}</id> |
|
||||
<minVersion>24.0</minVersion> |
|
||||
<maxVersion>56.*</maxVersion> |
|
||||
</r:Description> |
|
||||
</targetApplication> |
|
||||
|
|
||||
<!-- SeaMonkey --> |
|
||||
<targetApplication> |
|
||||
<r:Description> |
|
||||
<id>{{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}}</id> |
|
||||
<minVersion>2.24</minVersion> |
|
||||
<maxVersion>*</maxVersion> |
|
||||
</r:Description> |
|
||||
</targetApplication> |
|
||||
|
|
||||
<!-- Pale Moon --> |
|
||||
<targetApplication> |
|
||||
<r:Description> |
|
||||
<id>{{8de7fcbb-c55c-4fbe-bfc5-fc555c87dbc4}}</id> |
|
||||
<minVersion>26.0</minVersion> |
|
||||
<maxVersion>27.*</maxVersion> |
|
||||
</r:Description> |
|
||||
</targetApplication> |
|
||||
</r:Description> |
|
||||
</r: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="showLoggerButton"/> |
|
||||
</vbox> |
|
||||
</setting> |
|
||||
</vbox> |
|
@ -1,95 +0,0 @@ |
|||||
/******************************************************************************* |
|
||||
|
|
||||
uMatrix - a browser extension to block requests. |
|
||||
Copyright (C) 2017 Raymond Hill |
|
||||
|
|
||||
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/uMatrix
|
|
||||
|
|
||||
This file has been originally imported from: |
|
||||
https://github.com/gorhill/uBlock/tree/master/platform/chromium
|
|
||||
|
|
||||
*/ |
|
||||
|
|
||||
// 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; |
|
||||
}; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
// Patching for Pale Moon which does not implement ES6 Set/Map.
|
|
||||
// Test for non-ES6 Set/Map: check if property `iterator` is present.
|
|
||||
// The code is strictly to satisfy uBO's core, not to be an accurate
|
|
||||
// implementation of ES6.
|
|
||||
|
|
||||
if ( self.Set.prototype.iterator instanceof Function ) { |
|
||||
//console.log('Patching non-ES6 Set() to be more ES6-like.');
|
|
||||
self.Set.prototype._values = self.Set.prototype.values; |
|
||||
self.Set.prototype.values = function() { |
|
||||
this._valueIter = this._values(); |
|
||||
this.value = undefined; |
|
||||
this.done = false; |
|
||||
return this; |
|
||||
}; |
|
||||
self.Set.prototype.next = function() { |
|
||||
try { |
|
||||
this.value = this._valueIter.next(); |
|
||||
} catch (ex) { |
|
||||
this._valueIter = undefined; |
|
||||
this.value = undefined; |
|
||||
this.done = true; |
|
||||
} |
|
||||
return this; |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
if ( self.Map.prototype.iterator instanceof Function ) { |
|
||||
//console.log('Patching non-ES6 Map() to be more ES6-like.');
|
|
||||
self.Map.prototype._entries = self.Map.prototype.entries; |
|
||||
self.Map.prototype.entries = function() { |
|
||||
this._entryIter = this._entries(); |
|
||||
this.value = undefined; |
|
||||
this.done = false; |
|
||||
return this; |
|
||||
}; |
|
||||
self.Map.prototype.next = function() { |
|
||||
try { |
|
||||
this.value = this._entryIter.next(); |
|
||||
} catch (ex) { |
|
||||
this._entryIter = undefined; |
|
||||
this.value = undefined; |
|
||||
this.done = true; |
|
||||
} |
|
||||
return this; |
|
||||
}; |
|
||||
} |
|
||||
|
|
3465
platform/firefox/vapi-background.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,225 +0,0 @@ |
|||||
/******************************************************************************* |
|
||||
|
|
||||
uMatrix - a browser extension to block requests. |
|
||||
Copyright (C) 2014-2017 The uMatrix/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/uMatrix
|
|
||||
*/ |
|
||||
|
|
||||
/* jshint esnext: true */ |
|
||||
/* global addMessageListener, removeMessageListener, sendAsyncMessage */ |
|
||||
|
|
||||
// For non background pages
|
|
||||
|
|
||||
'use strict'; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
(function(self) { |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
// https://bugs.chromium.org/p/project-zero/issues/detail?id=1225&desc=6#c10
|
|
||||
if ( self.vAPI === undefined || self.vAPI.uMatrix !== true ) { |
|
||||
self.vAPI = { uMatrix: true }; |
|
||||
} |
|
||||
|
|
||||
var vAPI = self.vAPI; |
|
||||
vAPI.firefox = true; |
|
||||
vAPI.sessionId = String.fromCharCode(Date.now() % 25 + 97) + |
|
||||
Math.random().toString(36).slice(2); |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
vAPI.setTimeout = vAPI.setTimeout || function(callback, delay) { |
|
||||
return setTimeout(function() { callback(); }, delay); |
|
||||
}; |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
vAPI.shutdown = (function() { |
|
||||
var jobs = []; |
|
||||
|
|
||||
var add = function(job) { |
|
||||
jobs.push(job); |
|
||||
}; |
|
||||
|
|
||||
var exec = function() { |
|
||||
//console.debug('Shutting down...');
|
|
||||
var job; |
|
||||
while ( (job = jobs.pop()) ) { |
|
||||
job(); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
return { |
|
||||
add: add, |
|
||||
exec: exec |
|
||||
}; |
|
||||
})(); |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
vAPI.messaging = { |
|
||||
listeners: new Set(), |
|
||||
pending: new Map(), |
|
||||
requestId: 1, |
|
||||
connected: false, |
|
||||
|
|
||||
setup: function() { |
|
||||
this.addListener(this.builtinListener); |
|
||||
if ( this.toggleListenerCallback === null ) { |
|
||||
this.toggleListenerCallback = this.toggleListener.bind(this); |
|
||||
} |
|
||||
window.addEventListener('pagehide', this.toggleListenerCallback, true); |
|
||||
window.addEventListener('pageshow', this.toggleListenerCallback, true); |
|
||||
}, |
|
||||
|
|
||||
shutdown: function() { |
|
||||
if ( this.toggleListenerCallback !== null ) { |
|
||||
window.removeEventListener('pagehide', this.toggleListenerCallback, true); |
|
||||
window.removeEventListener('pageshow', this.toggleListenerCallback, true); |
|
||||
} |
|
||||
this.removeAllListeners(); |
|
||||
//service pending callbacks
|
|
||||
var pending = this.pending; |
|
||||
this.pending.clear(); |
|
||||
for ( var callback of pending.values() ) { |
|
||||
if ( typeof callback === 'function' ) { |
|
||||
callback(null); |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
connect: function() { |
|
||||
if ( !this.connected ) { |
|
||||
if ( this.messageListenerCallback === null ) { |
|
||||
this.messageListenerCallback = this.messageListener.bind(this); |
|
||||
} |
|
||||
addMessageListener(this.messageListenerCallback); |
|
||||
this.connected = true; |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
disconnect: function() { |
|
||||
if ( this.connected ) { |
|
||||
removeMessageListener(); |
|
||||
this.connected = false; |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
messageListener: function(msg) { |
|
||||
var details = JSON.parse(msg); |
|
||||
if ( !details ) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if ( details.broadcast ) { |
|
||||
this.sendToListeners(details.msg); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if ( details.requestId ) { |
|
||||
var listener = this.pending.get(details.requestId); |
|
||||
if ( listener !== undefined ) { |
|
||||
this.pending.delete(details.requestId); |
|
||||
listener(details.msg); |
|
||||
return; |
|
||||
} |
|
||||
} |
|
||||
}, |
|
||||
messageListenerCallback: null, |
|
||||
|
|
||||
builtinListener: function(msg) { |
|
||||
if ( typeof msg.cmd === 'string' && msg.cmd === 'injectScript' ) { |
|
||||
var details = msg.details; |
|
||||
if ( !details.allFrames && window !== window.top ) { |
|
||||
return; |
|
||||
} |
|
||||
self.injectScript(details.file); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
send: function(channelName, message, callback) { |
|
||||
this.connect() |
|
||||
|
|
||||
message = { |
|
||||
channelName: self._sandboxId_ + '|' + channelName, |
|
||||
msg: message |
|
||||
}; |
|
||||
|
|
||||
if ( callback ) { |
|
||||
message.requestId = this.requestId++; |
|
||||
this.pending.set(message.requestId, callback); |
|
||||
} |
|
||||
|
|
||||
sendAsyncMessage('umatrix:background', message); |
|
||||
}, |
|
||||
|
|
||||
toggleListener: function({type, persisted}) { |
|
||||
if ( type === 'pagehide' && !persisted ) { |
|
||||
vAPI.shutdown.exec(); |
|
||||
this.shutdown(); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if ( type === 'pagehide' ) { |
|
||||
this.disconnect(); |
|
||||
} else /* if ( type === 'pageshow' ) */ { |
|
||||
this.connect(); |
|
||||
} |
|
||||
}, |
|
||||
toggleListenerCallback: null, |
|
||||
|
|
||||
sendToListeners: function(msg) { |
|
||||
for ( var listener of this.listeners ) { |
|
||||
listener(msg); |
|
||||
} |
|
||||
}, |
|
||||
|
|
||||
addListener: function(listener) { |
|
||||
this.listeners.add(listener); |
|
||||
this.connect() |
|
||||
}, |
|
||||
|
|
||||
removeListener: function(listener) { |
|
||||
this.listeners.delete(listener); |
|
||||
}, |
|
||||
|
|
||||
removeAllListeners: function() { |
|
||||
this.disconnect(); |
|
||||
this.listeners.clear();; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
vAPI.messaging.setup() |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
// 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 ) { |
|
||||
vAPI.shutdown.add(function() { |
|
||||
vAPI = null; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
})(this); |
|
||||
|
|
||||
/******************************************************************************/ |
|
@ -1,191 +0,0 @@ |
|||||
/******************************************************************************* |
|
||||
|
|
||||
uMatrix - a browser extension to block requests. |
|
||||
Copyright (C) 2014-2017 The uMatrix/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/uMatrix
|
|
||||
*/ |
|
||||
|
|
||||
/* 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 === undefined || self.vAPI.uMatrix !== true ) { |
|
||||
self.vAPI = { uMatrix: 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.insertHTML = (function() { |
|
||||
const parser = Components.classes['@mozilla.org/parserutils;1'] |
|
||||
.getService(Components.interfaces.nsIParserUtils); |
|
||||
|
|
||||
// https://github.com/gorhill/uBlock/issues/845
|
|
||||
// Apparently dashboard pages execute with `about:blank` principal.
|
|
||||
|
|
||||
return function(node, html) { |
|
||||
while ( node.firstChild ) { |
|
||||
node.removeChild(node.firstChild); |
|
||||
} |
|
||||
|
|
||||
node.appendChild(parser.parseFragment( |
|
||||
html, |
|
||||
parser.SanitizerAllowStyle, |
|
||||
false, |
|
||||
Services.io.newURI('about:blank', null, null), |
|
||||
document.documentElement |
|
||||
)); |
|
||||
}; |
|
||||
})(); |
|
||||
|
|
||||
/******************************************************************************/ |
|
||||
|
|
||||
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 +0,0 @@ |
|||||
/* Firefox: no platform-specific code */ |
|
@ -1,120 +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 |
|
||||
from xml.sax.saxutils import escape |
|
||||
|
|
||||
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 |
|
||||
|
|
||||
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'] |
|
||||
|
|
||||
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 umatrix en ./locale/en/\n') |
|
||||
|
|
||||
for alpha2 in language_codes: |
|
||||
if alpha2 == 'en': |
|
||||
continue |
|
||||
|
|
||||
f.write(u'locale umatrix ' + alpha2 + ' ./locale/' + alpha2 + '/\n') |
|
||||
|
|
||||
rmtree(source_locale_dir) |
|
||||
|
|
||||
# update install.rdf |
|
||||
proj_dir = pj(os.path.split(os.path.abspath(__file__))[0], '..') |
|
||||
chromium_manifest = pj(proj_dir, 'platform', 'chromium', 'manifest.json') |
|
||||
|
|
||||
with open(chromium_manifest, encoding='utf-8') as m: |
|
||||
manifest = json.load(m) |
|
||||
|
|
||||
# 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*$' " |
|
||||
|
|
||||
match = re.search('^(\d+\.\d+\.\d+)(\.\d+)$', manifest['version']) |
|
||||
if match: |
|
||||
buildtype = int(match.group(2)[1:]) |
|
||||
if buildtype < 100: |
|
||||
builttype = 'b' + str(buildtype) |
|
||||
else: |
|
||||
builttype = 'rc' + str(buildtype - 100) |
|
||||
manifest['version'] = match.group(1) + builttype |
|
||||
|
|
||||
manifest['homepage'] = 'https://github.com/gorhill/uMatrix' |
|
||||
manifest['description'] = escape(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 + '<localized><r:Description>\n' + |
|
||||
t3 + '<locale>' + alpha2 + '</locale>\n' + |
|
||||
t3 + '<name>' + manifest['name'] + '</name>\n' + |
|
||||
t3 + '<description>' + escape(descriptions[alpha2]) + '</description>\n' + |
|
||||
t3 + '<creator>' + manifest['author'] + '</creator>\n' + |
|
||||
# t3 + '<translator>' + ??? + '</translator>\n' + |
|
||||
t3 + '<homepageURL>' + manifest['homepage'] + '</homepageURL>\n' + |
|
||||
t*2 + '</r:Description></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)) |
|
||||
f.truncate() |
|
@ -1,42 +0,0 @@ |
|||||
#!/bin/bash |
|
||||
# |
|
||||
# This script assumes a linux environment |
|
||||
|
|
||||
echo "*** uMatrix.firefox: Copying files" |
|
||||
|
|
||||
DES=dist/build/uMatrix.firefox |
|
||||
rm -rf $DES |
|
||||
mkdir -p $DES |
|
||||
|
|
||||
cp -R assets $DES/ |
|
||||
|
|
||||
|
|
||||
cp -R src/* $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/firefox/bootstrap.js $DES/ |
|
||||
cp platform/firefox/frame*.js $DES/ |
|
||||
cp -R platform/chromium/img $DES/ |
|
||||
cp platform/firefox/chrome.manifest $DES/ |
|
||||
cp platform/firefox/install.rdf $DES/ |
|
||||
cp platform/firefox/*.xul $DES/ |
|
||||
cp LICENSE.txt $DES/ |
|
||||
|
|
||||
echo "*** uMatrix.firefox: Generating meta..." |
|
||||
python tools/make-firefox-meta.py $DES/ |
|
||||
|
|
||||
if [ "$1" = all ]; then |
|
||||
echo "*** uMatrix.firefox: Creating package..." |
|
||||
pushd $DES/ |
|
||||
zip ../uMatrix.firefox.xpi -qr * |
|
||||
popd |
|
||||
fi |
|
||||
|
|
||||
echo "*** uMatrix.firefox: Package done." |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue