mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-26 04:12:50 +01:00
Firefox: blocking and content scripts for e10s
This commit is contained in:
parent
0f771e94d1
commit
e4329b7dfe
@ -140,6 +140,8 @@ vAPI.tabs.open = function(details) {
|
||||
};
|
||||
|
||||
if ( details.tabId ) {
|
||||
details.tabId = parseInt(tabId, 10);
|
||||
|
||||
// update doesn't accept index, must use move
|
||||
chrome.tabs.update(details.tabId, _details, function(tab) {
|
||||
// if the tab doesn't exist
|
||||
@ -203,7 +205,7 @@ vAPI.tabs.remove = function(tabId) {
|
||||
if ( vAPI.lastError() ) {
|
||||
}
|
||||
};
|
||||
chrome.tabs.remove(tabId, onTabRemoved);
|
||||
chrome.tabs.remove(parseInt(tabId, 10), onTabRemoved);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
@ -227,6 +229,7 @@ vAPI.tabs.injectScript = function(tabId, details, callback) {
|
||||
}
|
||||
};
|
||||
if ( tabId ) {
|
||||
tabid = parseInt(tabId, 10);
|
||||
chrome.tabs.executeScript(tabId, details, onScriptExecuted);
|
||||
} else {
|
||||
chrome.tabs.executeScript(details, onScriptExecuted);
|
||||
@ -243,6 +246,7 @@ vAPI.tabs.injectScript = function(tabId, details, callback) {
|
||||
// anymore, so this ensures it does still exist.
|
||||
|
||||
vAPI.setIcon = function(tabId, img, badge) {
|
||||
tabId = parseInt(tabId, 10);
|
||||
var onIconReady = function() {
|
||||
if ( vAPI.lastError() ) {
|
||||
return;
|
||||
|
169
platform/firefox/frameModule.js
Normal file
169
platform/firefox/frameModule.js
Normal file
@ -0,0 +1,169 @@
|
||||
/* global Services, Components, XPCOMUtils */
|
||||
/* exported EXPORTED_SYMBOLS, isTabbed */
|
||||
|
||||
'use strict';
|
||||
|
||||
var EXPORTED_SYMBOLS = ['contentPolicy', 'docObserver'];
|
||||
|
||||
Components.utils['import']('resource://gre/modules/Services.jsm');
|
||||
Components.utils['import']('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
const Ci = Components.interfaces, appName = 'ublock';
|
||||
|
||||
let getMessager = function(win) {
|
||||
try {
|
||||
// e10s
|
||||
return win
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.rootTreeItem
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
} catch (ex) {
|
||||
return win
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIContentFrameMessageManager);
|
||||
}
|
||||
};
|
||||
|
||||
let contentPolicy = {
|
||||
classDescription: 'ContentPolicy implementation',
|
||||
classID: Components.ID('{e6d173c8-8dbf-4189-a6fd-189e8acffd27}'),
|
||||
contractID: '@ublock/content-policy;1',
|
||||
ACCEPT: Ci.nsIContentPolicy.ACCEPT,
|
||||
REJECT: Ci.nsIContentPolicy.REJECT_REQUEST,
|
||||
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.nsIContentPolicy,
|
||||
Ci.nsISupportsWeakReference
|
||||
]),
|
||||
createInstance: function(outer, iid) {
|
||||
if (outer) {
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
register: function() {
|
||||
this.componentRegistrar.registerFactory(
|
||||
this.classID,
|
||||
this.classDescription,
|
||||
this.contractID,
|
||||
this
|
||||
);
|
||||
this.categoryManager.addCategoryEntry(
|
||||
'content-policy',
|
||||
this.contractID,
|
||||
this.contractID,
|
||||
false,
|
||||
true
|
||||
);
|
||||
},
|
||||
unregister: function() {
|
||||
this.componentRegistrar.unregisterFactory(this.classID, this);
|
||||
this.categoryManager.deleteCategoryEntry(
|
||||
'content-policy',
|
||||
this.contractID,
|
||||
false
|
||||
);
|
||||
},
|
||||
shouldLoad: function(type, location, origin, context) {
|
||||
if (type === 6 || !context || !/^https?$/.test(location.scheme)) {
|
||||
return this.ACCEPT;
|
||||
}
|
||||
|
||||
let win = (context.ownerDocument || context).defaultView;
|
||||
|
||||
if (!win) {
|
||||
return this.ACCEPT;
|
||||
}
|
||||
|
||||
let result = getMessager(win).sendSyncMessage('ublock:onBeforeRequest', {
|
||||
url: location.spec,
|
||||
type: type,
|
||||
tabId: -1,
|
||||
frameId: win === win.top ? 0 : 1,
|
||||
parentFrameId: win === win.top ? -1 : 0
|
||||
})[0];
|
||||
|
||||
return result === true ? this.REJECT : this.ACCEPT;
|
||||
}/*,
|
||||
shouldProcess: function() {
|
||||
return this.ACCEPT;
|
||||
}*/
|
||||
};
|
||||
|
||||
let docObserver = {
|
||||
contentBaseURI: 'chrome://ublock/content/js/',
|
||||
initContext: function(win, sandbox) {
|
||||
let messager = getMessager(win);
|
||||
|
||||
if (sandbox) {
|
||||
win = Components.utils.Sandbox([win], {
|
||||
sandboxPrototype: win,
|
||||
wantComponents: false,
|
||||
wantXHRConstructor: false
|
||||
});
|
||||
}
|
||||
|
||||
win.sendAsyncMessage = messager.sendAsyncMessage;
|
||||
win.addMessageListener = messager.ublock_addMessageListener;
|
||||
win.removeMessageListener = messager.ublock_removeMessageListener;
|
||||
|
||||
return win;
|
||||
},
|
||||
register: function() {
|
||||
Services.obs.addObserver(this, 'document-element-inserted', false);
|
||||
},
|
||||
unregister: function() {
|
||||
Services.obs.removeObserver(this, 'document-element-inserted');
|
||||
},
|
||||
observe: function(doc) {
|
||||
let win = doc.defaultView;
|
||||
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!/^https?:$/.test(win.location.protocol)) {
|
||||
if (win.location.protocol === 'chrome:'
|
||||
&& win.location.host === appName) {
|
||||
this.initContext(win);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let lss = Services.scriptloader.loadSubScript;
|
||||
win = this.initContext(win, true);
|
||||
|
||||
lss(this.contentBaseURI + 'vapi-client.js', win);
|
||||
lss(this.contentBaseURI + 'contentscript-start.js', win);
|
||||
|
||||
if (doc.readyState === 'interactive' || doc.readyState === 'complete') {
|
||||
lss(this.contentBaseURI + 'contentscript-end.js', win);
|
||||
}
|
||||
else {
|
||||
let docReady = function(e) {
|
||||
this.removeEventListener(e.type, docReady, true);
|
||||
lss(docObserver.contentBaseURI + 'contentscript-end.js', win);
|
||||
};
|
||||
|
||||
doc.addEventListener('DOMContentLoaded', docReady, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
contentPolicy.register();
|
||||
docObserver.register();
|
@ -1,22 +1,20 @@
|
||||
/* globals Services, sendAsyncMessage, addMessageListener, removeMessageListener, content */
|
||||
|
||||
(function() {
|
||||
/* globals Services, sendAsyncMessage, addMessageListener, removeMessageListener */
|
||||
|
||||
'use strict';
|
||||
|
||||
let appName = 'ublock';
|
||||
let contentBaseURI = 'chrome://' + appName + '/content/js/';
|
||||
let listeners = {};
|
||||
let frameModule = Components.utils['import']('chrome://' + appName + '/content/frameModule.js', {});
|
||||
|
||||
let _addMessageListener = function(id, fn) {
|
||||
_removeMessageListener(id);
|
||||
this.ublock_addMessageListener = function(id, fn) {
|
||||
ublock_removeMessageListener(id);
|
||||
listeners[id] = function(msg) {
|
||||
fn(msg.data);
|
||||
};
|
||||
addMessageListener(id, listeners[id]);
|
||||
};
|
||||
|
||||
let _removeMessageListener = function(id) {
|
||||
this.ublock_removeMessageListener = function(id) {
|
||||
if (listeners[id]) {
|
||||
removeMessageListener(id, listeners[id]);
|
||||
}
|
||||
@ -29,72 +27,3 @@ addMessageListener(appName + ':broadcast', function(msg) {
|
||||
listeners[id](msg);
|
||||
}
|
||||
});
|
||||
|
||||
let initContext = function(win, sandbox) {
|
||||
if (sandbox) {
|
||||
win = Components.utils.Sandbox([win], {
|
||||
sandboxPrototype: win,
|
||||
wantComponents: false,
|
||||
wantXHRConstructor: false
|
||||
});
|
||||
}
|
||||
|
||||
win.sendAsyncMessage = sendAsyncMessage;
|
||||
win.addMessageListener = _addMessageListener;
|
||||
win.removeMessageListener = _removeMessageListener;
|
||||
|
||||
return win;
|
||||
};
|
||||
|
||||
let observer = {
|
||||
observe: function(win) {
|
||||
if (!win || win.top !== content) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(win.document instanceof win.HTMLDocument
|
||||
&& (/^https?:$/.test(win.location.protocol)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
let lss = Services.scriptloader.loadSubScript;
|
||||
win = initContext(win, true);
|
||||
|
||||
lss(contentBaseURI + 'vapi-client.js', win);
|
||||
lss(contentBaseURI + 'contentscript-start.js', win);
|
||||
|
||||
let readyState = win.document.readyState;
|
||||
|
||||
if (readyState === "interactive" || readyState === "complete") {
|
||||
lss(contentBaseURI + 'contentscript-end.js', win);
|
||||
}
|
||||
else {
|
||||
let docReady = function(e) {
|
||||
this.removeEventListener(e.type, docReady, true);
|
||||
lss(contentBaseURI + 'contentscript-end.js', win);
|
||||
};
|
||||
|
||||
win.document.addEventListener('DOMContentLoaded', docReady, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Services.obs.addObserver(observer, 'content-document-global-created', false);
|
||||
|
||||
let DOMReady = function(e) {
|
||||
let win = e.target.defaultView;
|
||||
|
||||
// inject the message handlers for the options page
|
||||
if (win.location.protocol === 'chrome:' && win.location.host === appName) {
|
||||
initContext(win);
|
||||
}
|
||||
};
|
||||
|
||||
addEventListener('DOMContentLoaded', DOMReady, true);
|
||||
|
||||
addEventListener('unload', function() {
|
||||
Services.obs.removeObserver(observer, 'content-document-global-created');
|
||||
observer = listeners = null;
|
||||
}, false);
|
||||
|
||||
})();
|
@ -19,7 +19,7 @@
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
/* global Services, XPCOMUtils */
|
||||
/* global Services */
|
||||
|
||||
// For background page
|
||||
|
||||
@ -34,7 +34,6 @@
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
|
||||
|
||||
Cu['import']('resource://gre/modules/Services.jsm');
|
||||
Cu['import']('resource://gre/modules/XPCOMUtils.jsm');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@ -236,7 +235,7 @@ var windowWatcher = {
|
||||
onTabClose: function(e) {
|
||||
vAPI.tabs.onClosed(vAPI.tabs.getTabId(e.target));
|
||||
},
|
||||
onTabSelect: function(e) {
|
||||
onTabSelect: function() {
|
||||
// vAPI.setIcon();
|
||||
},
|
||||
onLoad: function(e) {
|
||||
@ -338,7 +337,7 @@ vAPI.tabs.getTabId = function(target) {
|
||||
var i = gBrowser.browsers.indexOf(target);
|
||||
|
||||
if (i !== -1) {
|
||||
i = this.getTabId(gBrowser.tabs[i]);
|
||||
i = gBrowser.tabs[i].linkedPanel.slice(6);
|
||||
}
|
||||
|
||||
return i;
|
||||
@ -638,133 +637,69 @@ vAPI.messaging.unload = function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.lastError = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var conentPolicy = {
|
||||
classDescription: vAPI.app.name + ' ContentPolicy',
|
||||
classID: Components.ID('{e6d173c8-8dbf-4189-a6fd-189e8acffd27}'),
|
||||
contractID: '@' + vAPI.app.cleanName + '/content-policy;1',
|
||||
ACCEPT: Ci.nsIContentPolicy.ACCEPT,
|
||||
REJECT: Ci.nsIContentPolicy.REJECT_REQUEST,
|
||||
types: {
|
||||
7: 'sub_frame',
|
||||
4: 'stylesheet',
|
||||
2: 'script',
|
||||
3: 'image',
|
||||
5: 'object',
|
||||
11: 'xmlhttprequest'
|
||||
},
|
||||
get registrar() {
|
||||
return Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
},
|
||||
get catManager() {
|
||||
return Cc['@mozilla.org/categorymanager;1']
|
||||
.getService(Ci.nsICategoryManager);
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIFactory,
|
||||
Ci.nsIContentPolicy,
|
||||
Ci.nsISupportsWeakReference
|
||||
]),
|
||||
createInstance: function(outer, iid) {
|
||||
if (outer) {
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
}
|
||||
|
||||
return this.QueryInterface(iid);
|
||||
},
|
||||
shouldLoad: function(type, location, origin, context) {
|
||||
if (type === 6 || !context || !/^https?$/.test(location.scheme)) {
|
||||
return this.ACCEPT;
|
||||
}
|
||||
|
||||
var win = (context.ownerDocument || context).defaultView;
|
||||
|
||||
if (!win) {
|
||||
return this.ACCEPT;
|
||||
}
|
||||
|
||||
var block = vAPI.net.onBeforeRequest;
|
||||
|
||||
type = this.types[type] || 'other';
|
||||
|
||||
if (block.types.indexOf(type) === -1) {
|
||||
return this.ACCEPT;
|
||||
}
|
||||
|
||||
var browser = win.top.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShell)
|
||||
.chromeEventHandler;
|
||||
|
||||
if (!browser) {
|
||||
return this.ACCEPT;
|
||||
}
|
||||
|
||||
block = block.callback({
|
||||
url: location.spec,
|
||||
type: type,
|
||||
tabId: vAPI.tabs.getTabId(browser),
|
||||
frameId: win === win.top ? 0 : 1,
|
||||
parentFrameId: win === win.top ? -1 : 0
|
||||
});
|
||||
|
||||
if (block && typeof block === 'object') {
|
||||
if (block.cancel === true) {
|
||||
return this.REJECT;
|
||||
}
|
||||
else if (block.redirectURL) {
|
||||
location.spec = block.redirectURL;
|
||||
return this.REJECT;
|
||||
}
|
||||
}
|
||||
|
||||
return this.ACCEPT;
|
||||
},/*
|
||||
shouldProcess: function() {
|
||||
return this.ACCEPT;
|
||||
}*/
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net = {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net.registerListeners = function() {
|
||||
conentPolicy.registrar.registerFactory(
|
||||
conentPolicy.classID,
|
||||
conentPolicy.classDescription,
|
||||
conentPolicy.contractID,
|
||||
conentPolicy
|
||||
);
|
||||
conentPolicy.catManager.addCategoryEntry(
|
||||
'content-policy',
|
||||
conentPolicy.contractID,
|
||||
conentPolicy.contractID,
|
||||
false,
|
||||
true
|
||||
var types = {
|
||||
2: 'script',
|
||||
3: 'image',
|
||||
4: 'stylesheet',
|
||||
5: 'object',
|
||||
7: 'sub_frame',
|
||||
11: 'xmlhttprequest'
|
||||
};
|
||||
|
||||
var onBeforeRequest = this.onBeforeRequest;
|
||||
|
||||
this.onBeforeRequest = function(e) {
|
||||
var details = e.data;
|
||||
|
||||
details.type = types[details.type] || 'other';
|
||||
details.tabId = vAPI.tabs.getTabId(e.target);
|
||||
|
||||
if (onBeforeRequest.types.indexOf(details.type) === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var block = onBeforeRequest.callback(details);
|
||||
|
||||
if (block && typeof block === 'object') {
|
||||
if (block.cancel === true) {
|
||||
return true;
|
||||
}
|
||||
else if (block.redirectURL) {
|
||||
return block.redirectURL;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
vAPI.messaging.gmm.addMessageListener(
|
||||
vAPI.app.cleanName + ':onBeforeRequest',
|
||||
this.onBeforeRequest
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.net.unregisterListeners = function() {
|
||||
conentPolicy.registrar.unregisterFactory(conentPolicy.classID, conentPolicy);
|
||||
conentPolicy.catManager.deleteCategoryEntry(
|
||||
'content-policy',
|
||||
conentPolicy.contractID,
|
||||
false
|
||||
vAPI.messaging.gmm.removeMessageListener(
|
||||
vAPI.app.cleanName + ':onBeforeRequest',
|
||||
this.onBeforeRequest
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.lastError = function() {
|
||||
return null;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// clean up when the extension is disabled
|
||||
|
||||
window.addEventListener('unload', function() {
|
||||
@ -773,14 +708,21 @@ window.addEventListener('unload', function() {
|
||||
vAPI.messaging.unload();
|
||||
vAPI.net.unregisterListeners();
|
||||
|
||||
var URI = vAPI.messaging.frameScript.replace('Script.', 'Module.');
|
||||
var frameModule = {};
|
||||
Cu['import'](URI, frameModule);
|
||||
frameModule.contentPolicy.unregister();
|
||||
frameModule.docObserver.unregister();
|
||||
Cu.unload(URI);
|
||||
|
||||
// close extension tabs
|
||||
var extURI, win, tab, host = vAPI.app.cleanName;
|
||||
var win, tab, host = vAPI.app.cleanName;
|
||||
|
||||
for (win of vAPI.tabs.getWindows()) {
|
||||
for (tab of win.gBrowser.tabs) {
|
||||
extURI = tab.linkedBrowser.currentURI;
|
||||
URI = tab.linkedBrowser.currentURI;
|
||||
|
||||
if (extURI.scheme === 'chrome' && extURI.host === host) {
|
||||
if (URI.scheme === 'chrome' && URI.host === host) {
|
||||
win.gBrowser.removeTab(tab);
|
||||
}
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ vAPI.storage = {
|
||||
|
||||
vAPI.tabs = {
|
||||
stack: {},
|
||||
stackID: 1
|
||||
stackId: 1
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
@ -374,21 +374,17 @@ vAPI.tabs.injectScript = function(tabId, details, callback) {
|
||||
j = wins[i].tabs.length;
|
||||
|
||||
while (j--) {
|
||||
tabs.push(wins[i].tabs[j]);
|
||||
vAPI.tabs.stack[vAPI.tabs.stackId++] = wins[i].tabs[j];
|
||||
}
|
||||
}
|
||||
|
||||
return tabs;
|
||||
})().forEach(function(tab) {
|
||||
vAPI.tabs.stack[vAPI.tabs.stackID++] = tab;
|
||||
});
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
safari.application.addEventListener('open', function(e) {
|
||||
// ignore windows
|
||||
if (e.target instanceof SafariBrowserTab) {
|
||||
vAPI.tabs.stack[vAPI.tabs.stackID++] = e.target;
|
||||
vAPI.tabs.stack[vAPI.tabs.stackId++] = e.target;
|
||||
}
|
||||
}, true);
|
||||
|
||||
@ -402,7 +398,7 @@ safari.application.addEventListener('close', function(e) {
|
||||
|
||||
var tabId = vAPI.tabs.getTabId(e.target);
|
||||
|
||||
if (tabId > -1) {
|
||||
if (tabId !== -1) {
|
||||
// to not add another listener, put this here
|
||||
// instead of vAPI.tabs.registerListeners
|
||||
if (typeof vAPI.tabs.onClosed === 'function') {
|
||||
|
@ -19,6 +19,7 @@ cp src/img/icon_128.png $DES/icon.png
|
||||
cp platform/firefox/vapi-*.js $DES/js/
|
||||
cp platform/firefox/bootstrap.js $DES/
|
||||
cp platform/firefox/frameScript.js $DES/
|
||||
cp platform/firefox/frameModule.js $DES/
|
||||
cp platform/firefox/chrome.manifest $DES/
|
||||
cp platform/firefox/install.rdf $DES/
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user