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