mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 09:07:54 +01:00
#1163: this implements "block elements by size"
This commit is contained in:
parent
08d7ce96aa
commit
89148351e8
32 changed files with 1047 additions and 522 deletions
|
@ -245,10 +245,6 @@ vAPI.tabs.registerListeners = function() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var onUpdated = function(tabId, changeInfo, tab) {
|
|
||||||
onUpdatedClient(tabId, changeInfo, tab);
|
|
||||||
};
|
|
||||||
|
|
||||||
var onCommitted = function(details) {
|
var onCommitted = function(details) {
|
||||||
if ( details.frameId !== 0 ) {
|
if ( details.frameId !== 0 ) {
|
||||||
return;
|
return;
|
||||||
|
@ -256,9 +252,18 @@ vAPI.tabs.registerListeners = function() {
|
||||||
onNavigationClient(details);
|
onNavigationClient(details);
|
||||||
};
|
};
|
||||||
|
|
||||||
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
|
var onActivated = function(details) {
|
||||||
|
vAPI.contextMenu.onMustUpdate(details.tabId);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onUpdated = function(tabId, changeInfo, tab) {
|
||||||
|
onUpdatedClient(tabId, changeInfo, tab);
|
||||||
|
};
|
||||||
|
|
||||||
chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
|
chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
|
||||||
chrome.webNavigation.onCommitted.addListener(onCommitted);
|
chrome.webNavigation.onCommitted.addListener(onCommitted);
|
||||||
|
chrome.webNavigation.onCreatedNavigationTarget.addListener(onCreatedNavigationTarget);
|
||||||
|
chrome.tabs.onActivated.addListener(onActivated);
|
||||||
chrome.tabs.onUpdated.addListener(onUpdated);
|
chrome.tabs.onUpdated.addListener(onUpdated);
|
||||||
|
|
||||||
if ( typeof this.onClosed === 'function' ) {
|
if ( typeof this.onClosed === 'function' ) {
|
||||||
|
@ -291,9 +296,7 @@ vAPI.tabs.get = function(tabId, callback) {
|
||||||
|
|
||||||
var onTabReceived = function(tabs) {
|
var onTabReceived = function(tabs) {
|
||||||
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
// https://code.google.com/p/chromium/issues/detail?id=410868#c8
|
||||||
if ( chrome.runtime.lastError ) {
|
void chrome.runtime.lastError;
|
||||||
/* noop */
|
|
||||||
}
|
|
||||||
callback(tabs[0]);
|
callback(tabs[0]);
|
||||||
};
|
};
|
||||||
chrome.tabs.query({ active: true, currentWindow: true }, onTabReceived);
|
chrome.tabs.query({ active: true, currentWindow: true }, onTabReceived);
|
||||||
|
@ -553,6 +556,7 @@ vAPI.setIcon = function(tabId, iconStatus, badge) {
|
||||||
{ '19': 'img/browsericons/icon19-off.png', '38': 'img/browsericons/icon38-off.png' };
|
{ '19': 'img/browsericons/icon19-off.png', '38': 'img/browsericons/icon38-off.png' };
|
||||||
|
|
||||||
chrome.browserAction.setIcon({ tabId: tabId, path: iconPaths }, onIconReady);
|
chrome.browserAction.setIcon({ tabId: tabId, path: iconPaths }, onIconReady);
|
||||||
|
vAPI.contextMenu.onMustUpdate(tabId);
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -784,6 +788,51 @@ vAPI.net.registerListeners = function() {
|
||||||
var µb = µBlock;
|
var µb = µBlock;
|
||||||
var µburi = µb.URI;
|
var µburi = µb.URI;
|
||||||
|
|
||||||
|
// Chromium-based browsers understand only these network request types.
|
||||||
|
var validTypes = {
|
||||||
|
'main_frame': true,
|
||||||
|
'sub_frame': true,
|
||||||
|
'stylesheet': true,
|
||||||
|
'script': true,
|
||||||
|
'image': true,
|
||||||
|
'object': true,
|
||||||
|
'xmlhttprequest': true,
|
||||||
|
'other': true
|
||||||
|
};
|
||||||
|
|
||||||
|
var denormalizeTypes = function(aa) {
|
||||||
|
if ( aa.length === 0 ) {
|
||||||
|
return Object.keys(validTypes);
|
||||||
|
}
|
||||||
|
var out = [];
|
||||||
|
var i = aa.length,
|
||||||
|
type,
|
||||||
|
needOther = true;
|
||||||
|
while ( i-- ) {
|
||||||
|
type = aa[i];
|
||||||
|
if ( validTypes.hasOwnProperty(type) ) {
|
||||||
|
out.push(type);
|
||||||
|
}
|
||||||
|
if ( type === 'other' ) {
|
||||||
|
needOther = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( needOther ) {
|
||||||
|
out.push('other');
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
var headerValue = function(headers, name) {
|
||||||
|
var i = headers.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
if ( headers[i].name.toLowerCase() === name ) {
|
||||||
|
return headers[i].value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
var normalizeRequestDetails = function(details) {
|
var normalizeRequestDetails = function(details) {
|
||||||
µburi.set(details.url);
|
µburi.set(details.url);
|
||||||
|
|
||||||
|
@ -801,36 +850,47 @@ vAPI.net.registerListeners = function() {
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/862
|
// https://github.com/chrisaljoudi/uBlock/issues/862
|
||||||
// If no transposition possible, transpose to `object` as per
|
// If no transposition possible, transpose to `object` as per
|
||||||
// Chromium bug 410382 (see below)
|
// Chromium bug 410382 (see below)
|
||||||
if ( pos === -1 ) {
|
if ( pos !== -1 ) {
|
||||||
details.type = 'object';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ext = tail.slice(pos) + '.';
|
var ext = tail.slice(pos) + '.';
|
||||||
if ( '.eot.ttf.otf.svg.woff.woff2.'.indexOf(ext) !== -1 ) {
|
if ( '.eot.ttf.otf.svg.woff.woff2.'.indexOf(ext) !== -1 ) {
|
||||||
details.type = 'font';
|
details.type = 'font';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( '.mp3.mp4.webm.'.indexOf(ext) !== -1 ) {
|
||||||
|
details.type = 'media';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Still need this because often behind-the-scene requests are wrongly
|
// Still need this because often behind-the-scene requests are wrongly
|
||||||
// categorized as 'other'
|
// categorized as 'other'
|
||||||
if ( '.ico.png.gif.jpg.jpeg.webp.'.indexOf(ext) !== -1 ) {
|
if ( '.ico.png.gif.jpg.jpeg.webp.'.indexOf(ext) !== -1 ) {
|
||||||
details.type = 'image';
|
details.type = 'image';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to extract type from response headers if present.
|
||||||
|
if ( details.responseHeaders ) {
|
||||||
|
var contentType = headerValue(details.responseHeaders, 'content-type');
|
||||||
|
if ( contentType.startsWith('font/') ) {
|
||||||
|
details.type = 'font';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( contentType.startsWith('image/') ) {
|
||||||
|
details.type = 'image';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( contentType.startsWith('audio/') || contentType.startsWith('video/') ) {
|
||||||
|
details.type = 'media';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://code.google.com/p/chromium/issues/detail?id=410382
|
// https://code.google.com/p/chromium/issues/detail?id=410382
|
||||||
details.type = 'object';
|
details.type = 'object';
|
||||||
};
|
};
|
||||||
|
|
||||||
var headerValue = function(headers, name) {
|
|
||||||
var i = headers.length;
|
|
||||||
while ( i-- ) {
|
|
||||||
if ( headers[i].name.toLowerCase() === name ) {
|
|
||||||
return headers[i].value.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
};
|
|
||||||
|
|
||||||
var onBeforeRequestClient = this.onBeforeRequest.callback;
|
var onBeforeRequestClient = this.onBeforeRequest.callback;
|
||||||
var onBeforeRequest = function(details) {
|
var onBeforeRequest = function(details) {
|
||||||
normalizeRequestDetails(details);
|
normalizeRequestDetails(details);
|
||||||
|
@ -839,13 +899,7 @@ vAPI.net.registerListeners = function() {
|
||||||
|
|
||||||
var onHeadersReceivedClient = this.onHeadersReceived.callback;
|
var onHeadersReceivedClient = this.onHeadersReceived.callback;
|
||||||
var onHeadersReceivedClientTypes = this.onHeadersReceived.types.slice(0);
|
var onHeadersReceivedClientTypes = this.onHeadersReceived.types.slice(0);
|
||||||
var onHeadersReceivedTypes = onHeadersReceivedClientTypes.slice(0);
|
var onHeadersReceivedTypes = denormalizeTypes(onHeadersReceivedClientTypes);
|
||||||
if (
|
|
||||||
onHeadersReceivedTypes.length !== 0 &&
|
|
||||||
onHeadersReceivedTypes.indexOf('other') === -1
|
|
||||||
) {
|
|
||||||
onHeadersReceivedTypes.push('other');
|
|
||||||
}
|
|
||||||
var onHeadersReceived = function(details) {
|
var onHeadersReceived = function(details) {
|
||||||
normalizeRequestDetails(details);
|
normalizeRequestDetails(details);
|
||||||
// Hack to work around Chromium API limitations, where requests of
|
// Hack to work around Chromium API limitations, where requests of
|
||||||
|
@ -857,9 +911,7 @@ vAPI.net.registerListeners = function() {
|
||||||
// `other` always becomes `object` when it can't be normalized into
|
// `other` always becomes `object` when it can't be normalized into
|
||||||
// something else. Test case for "unfriendly" font URLs:
|
// something else. Test case for "unfriendly" font URLs:
|
||||||
// https://www.google.com/fonts
|
// https://www.google.com/fonts
|
||||||
if ( details.type === 'object' ) {
|
if ( details.type === 'font' ) {
|
||||||
if ( headerValue(details.responseHeaders, 'content-type').startsWith('font/') ) {
|
|
||||||
details.type = 'font';
|
|
||||||
var r = onBeforeRequestClient(details);
|
var r = onBeforeRequestClient(details);
|
||||||
if ( typeof r === 'object' && r.cancel === true ) {
|
if ( typeof r === 'object' && r.cancel === true ) {
|
||||||
return { cancel: true };
|
return { cancel: true };
|
||||||
|
@ -871,7 +923,6 @@ vAPI.net.registerListeners = function() {
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return onHeadersReceivedClient(details);
|
return onHeadersReceivedClient(details);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -921,15 +972,46 @@ vAPI.net.registerListeners = function() {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.contextMenu = {
|
vAPI.contextMenu = {
|
||||||
create: function(details, callback) {
|
_callback: null,
|
||||||
this.menuId = details.id;
|
_entries: [],
|
||||||
this.callback = callback;
|
_createEntry: function(entry) {
|
||||||
chrome.contextMenus.create(details);
|
chrome.contextMenus.create(JSON.parse(JSON.stringify(entry)), function() {
|
||||||
chrome.contextMenus.onClicked.addListener(this.callback);
|
void chrome.runtime.lastError;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
remove: function() {
|
onMustUpdate: function() {},
|
||||||
chrome.contextMenus.onClicked.removeListener(this.callback);
|
setEntries: function(entries, callback) {
|
||||||
chrome.contextMenus.remove(this.menuId);
|
entries = entries || [];
|
||||||
|
var n = Math.max(this._entries.length, entries.length),
|
||||||
|
oldEntryId, newEntry;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
oldEntryId = this._entries[i];
|
||||||
|
newEntry = entries[i];
|
||||||
|
if ( oldEntryId && newEntry ) {
|
||||||
|
if ( newEntry.id !== oldEntryId ) {
|
||||||
|
chrome.contextMenus.remove(oldEntryId);
|
||||||
|
this._createEntry(newEntry);
|
||||||
|
this._entries[i] = newEntry.id;
|
||||||
|
}
|
||||||
|
} else if ( oldEntryId && !newEntry ) {
|
||||||
|
chrome.contextMenus.remove(oldEntryId);
|
||||||
|
} else if ( !oldEntryId && newEntry ) {
|
||||||
|
this._createEntry(newEntry);
|
||||||
|
this._entries[i] = newEntry.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = this._entries.length = entries.length;
|
||||||
|
callback = callback || null;
|
||||||
|
if ( callback === this._callback ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( n !== 0 && callback !== null ) {
|
||||||
|
chrome.contextMenus.onClicked.addListener(callback);
|
||||||
|
this._callback = callback;
|
||||||
|
} else if ( n === 0 && this._callback !== null ) {
|
||||||
|
chrome.contextMenus.onClicked.removeListener(this._callback);
|
||||||
|
this._callback = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global HTMLDocument, XMLDocument */
|
||||||
|
|
||||||
// For non background pages
|
// For non background pages
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -29,6 +31,18 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// https://github.com/chrisaljoudi/uBlock/issues/464
|
||||||
|
if ( document instanceof HTMLDocument === false ) {
|
||||||
|
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
||||||
|
// A XMLDocument can be a valid HTML document.
|
||||||
|
if (
|
||||||
|
document instanceof XMLDocument === false ||
|
||||||
|
document.createElement('div') instanceof HTMLDivElement === false
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/1124
|
// https://github.com/gorhill/uBlock/issues/1124
|
||||||
// Looks like `contentType` is on track to be standardized:
|
// Looks like `contentType` is on track to be standardized:
|
||||||
// https://dom.spec.whatwg.org/#concept-document-content-type
|
// https://dom.spec.whatwg.org/#concept-document-content-type
|
||||||
|
@ -43,12 +57,10 @@ var chrome = self.chrome;
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/456
|
// https://github.com/chrisaljoudi/uBlock/issues/456
|
||||||
// Already injected?
|
// Already injected?
|
||||||
if ( vAPI.vapiClientInjected ) {
|
if ( vAPI.sessionId ) {
|
||||||
//console.debug('vapi-client.js already injected: skipping.');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vAPI.vapiClientInjected = true;
|
|
||||||
vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) +
|
vAPI.sessionId = String.fromCharCode(Date.now() % 26 + 97) +
|
||||||
Math.random().toString(36).slice(2);
|
Math.random().toString(36).slice(2);
|
||||||
vAPI.chrome = true;
|
vAPI.chrome = true;
|
||||||
|
@ -67,7 +79,6 @@ vAPI.shutdown = (function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
var exec = function() {
|
var exec = function() {
|
||||||
//console.debug('Shutting down...');
|
|
||||||
var job;
|
var job;
|
||||||
while ( (job = jobs.pop()) ) {
|
while ( (job = jobs.pop()) ) {
|
||||||
job();
|
job();
|
||||||
|
@ -89,28 +100,34 @@ vAPI.messaging = {
|
||||||
pendingCount: 0,
|
pendingCount: 0,
|
||||||
auxProcessId: 1,
|
auxProcessId: 1,
|
||||||
|
|
||||||
|
onDisconnect: function() {
|
||||||
|
this.port = null;
|
||||||
|
this.close();
|
||||||
|
vAPI.shutdown.exec();
|
||||||
|
},
|
||||||
|
|
||||||
setup: function() {
|
setup: function() {
|
||||||
try {
|
try {
|
||||||
this.port = chrome.runtime.connect({name: vAPI.sessionId});
|
this.port = chrome.runtime.connect({name: vAPI.sessionId}) || null;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
}
|
}
|
||||||
if ( this.port === null ) {
|
if ( this.port === null ) {
|
||||||
//console.error("uBlock> Can't patch things up. It's over.");
|
|
||||||
vAPI.shutdown.exec();
|
vAPI.shutdown.exec();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.port.onMessage.addListener(messagingConnector);
|
this.port.onMessage.addListener(messagingConnector);
|
||||||
|
this.port.onDisconnect.addListener(this.onDisconnect.bind(this));
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
close: function() {
|
close: function() {
|
||||||
var port = this.port;
|
var port = this.port;
|
||||||
if ( port === null ) {
|
if ( port !== null ) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.port = null;
|
|
||||||
port.disconnect();
|
port.disconnect();
|
||||||
port.onMessage.removeListener(messagingConnector);
|
port.onMessage.removeListener(messagingConnector);
|
||||||
|
port.onDisconnect.removeListener(this.onDisconnect);
|
||||||
|
this.port = null;
|
||||||
|
}
|
||||||
this.channels = {};
|
this.channels = {};
|
||||||
// service pending callbacks
|
// service pending callbacks
|
||||||
var pending = this.pending, listener;
|
var pending = this.pending, listener;
|
||||||
|
|
|
@ -1440,6 +1440,7 @@ vAPI.setIcon = function(tabId, iconStatus, badge) {
|
||||||
|
|
||||||
if ( tabId === curTabId ) {
|
if ( tabId === curTabId ) {
|
||||||
tb.updateState(win, tabId);
|
tb.updateState(win, tabId);
|
||||||
|
vAPI.contextMenu.onMustUpdate(tabId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2064,18 +2065,24 @@ var httpObserver = {
|
||||||
},
|
},
|
||||||
|
|
||||||
handleResponseHeaders: function(channel, URI, channelData) {
|
handleResponseHeaders: function(channel, URI, channelData) {
|
||||||
var type = this.typeMap[channelData[3]] || 'other';
|
var requestType = this.typeMap[channelData[3]] || 'other';
|
||||||
if ( this.onHeadersReceivedTypes && this.onHeadersReceivedTypes.has(type) === false ) {
|
if ( this.onHeadersReceivedTypes && this.onHeadersReceivedTypes.has(requestType) === false ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'Content-Security-Policy' MUST come last in the array. Need to
|
// 'Content-Security-Policy' MUST come last in the array. Need to
|
||||||
// revised this eventually.
|
// revised this eventually.
|
||||||
var responseHeaders = [];
|
var responseHeaders = [];
|
||||||
var value = this.getResponseHeader(channel, 'Content-Security-Policy');
|
var value = channel.contentLength;
|
||||||
|
if ( value !== -1 ) {
|
||||||
|
responseHeaders.push({ name: 'Content-Length', value: value });
|
||||||
|
}
|
||||||
|
if ( requestType.endsWith('_frame') ) {
|
||||||
|
value = this.getResponseHeader(channel, 'Content-Security-Policy');
|
||||||
if ( value !== undefined ) {
|
if ( value !== undefined ) {
|
||||||
responseHeaders.push({ name: 'Content-Security-Policy', value: value });
|
responseHeaders.push({ name: 'Content-Security-Policy', value: value });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/966
|
// https://github.com/gorhill/uBlock/issues/966
|
||||||
var hostname = URI.asciiHost;
|
var hostname = URI.asciiHost;
|
||||||
|
@ -2088,7 +2095,7 @@ var httpObserver = {
|
||||||
parentFrameId: channelData[1],
|
parentFrameId: channelData[1],
|
||||||
responseHeaders: responseHeaders,
|
responseHeaders: responseHeaders,
|
||||||
tabId: channelData[2],
|
tabId: channelData[2],
|
||||||
type: this.typeMap[channelData[3]] || 'other',
|
type: requestType,
|
||||||
url: URI.asciiSpec
|
url: URI.asciiSpec
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2179,7 +2186,7 @@ var httpObserver = {
|
||||||
|
|
||||||
// Carry data for behind-the-scene redirects
|
// Carry data for behind-the-scene redirects
|
||||||
if ( channel instanceof Ci.nsIWritablePropertyBag ) {
|
if ( channel instanceof Ci.nsIWritablePropertyBag ) {
|
||||||
channel.setProperty( this.REQDATAKEY, [0, -1, null, vAPI.noTabId, rawtype]);
|
channel.setProperty(this.REQDATAKEY, [0, -1, vAPI.noTabId, rawtype]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -3171,173 +3178,20 @@ if ( vAPI.toolbarButton.init !== null ) {
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.contextMenu = {
|
vAPI.contextMenu = (function() {
|
||||||
contextMap: {
|
var clientCallback = null;
|
||||||
|
var clientEntries = [];
|
||||||
|
|
||||||
|
var contextMap = {
|
||||||
frame: 'inFrame',
|
frame: 'inFrame',
|
||||||
link: 'onLink',
|
link: 'onLink',
|
||||||
image: 'onImage',
|
image: 'onImage',
|
||||||
audio: 'onAudio',
|
audio: 'onAudio',
|
||||||
video: 'onVideo',
|
video: 'onVideo',
|
||||||
editable: 'onEditableArea'
|
editable: 'onEditableArea'
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.contextMenu.displayMenuItem = function({target}) {
|
|
||||||
var doc = target.ownerDocument;
|
|
||||||
var gContextMenu = doc.defaultView.gContextMenu;
|
|
||||||
if ( !gContextMenu.browser ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var menuitem = doc.getElementById(vAPI.contextMenu.menuItemId);
|
|
||||||
var currentURI = gContextMenu.browser.currentURI;
|
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/105
|
|
||||||
// TODO: Should the element picker works on any kind of pages?
|
|
||||||
if ( !currentURI.schemeIs('http') && !currentURI.schemeIs('https') ) {
|
|
||||||
menuitem.setAttribute('hidden', true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ctx = vAPI.contextMenu.contexts;
|
|
||||||
|
|
||||||
if ( !ctx ) {
|
|
||||||
menuitem.setAttribute('hidden', false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ctxMap = vAPI.contextMenu.contextMap;
|
|
||||||
|
|
||||||
for ( var context of ctx ) {
|
|
||||||
if (
|
|
||||||
context === 'page' &&
|
|
||||||
!gContextMenu.onLink &&
|
|
||||||
!gContextMenu.onImage &&
|
|
||||||
!gContextMenu.onEditableArea &&
|
|
||||||
!gContextMenu.inFrame &&
|
|
||||||
!gContextMenu.onVideo &&
|
|
||||||
!gContextMenu.onAudio
|
|
||||||
) {
|
|
||||||
menuitem.setAttribute('hidden', false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
ctxMap.hasOwnProperty(context) &&
|
|
||||||
gContextMenu[ctxMap[context]]
|
|
||||||
) {
|
|
||||||
menuitem.setAttribute('hidden', false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
menuitem.setAttribute('hidden', true);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.contextMenu.register = (function() {
|
|
||||||
var register = function(window) {
|
|
||||||
if ( canRegister(window) !== true ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !this.menuItemId ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( vAPI.fennec ) {
|
|
||||||
// TODO https://developer.mozilla.org/en-US/Add-ons/Firefox_for_Android/API/NativeWindow/contextmenus/add
|
|
||||||
/*var nativeWindow = doc.defaultView.NativeWindow;
|
|
||||||
contextId = nativeWindow.contextmenus.add(
|
|
||||||
this.menuLabel,
|
|
||||||
nativeWindow.contextmenus.linkOpenableContext,
|
|
||||||
this.onCommand
|
|
||||||
);*/
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Already installed?
|
|
||||||
var doc = window.document;
|
|
||||||
if ( doc.getElementById(this.menuItemId) !== null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var contextMenu = doc.getElementById('contentAreaContextMenu');
|
|
||||||
|
|
||||||
// This can happen (Thunderbird).
|
|
||||||
if ( contextMenu === null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var menuitem = doc.createElement('menuitem');
|
|
||||||
menuitem.setAttribute('id', this.menuItemId);
|
|
||||||
menuitem.setAttribute('label', this.menuLabel);
|
|
||||||
menuitem.setAttribute('image', vAPI.getURL('img/browsericons/icon16.svg'));
|
|
||||||
menuitem.setAttribute('class', 'menuitem-iconic');
|
|
||||||
menuitem.addEventListener('command', this.onCommand);
|
|
||||||
contextMenu.addEventListener('popupshowing', this.displayMenuItem);
|
|
||||||
contextMenu.insertBefore(menuitem, doc.getElementById('inspect-separator'));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/906
|
var onCommand = function() {
|
||||||
// Be sure document.readyState is 'complete': it could happen at launch
|
|
||||||
// time that we are called by vAPI.contextMenu.create() directly before
|
|
||||||
// the environment is properly initialized.
|
|
||||||
var canRegister = function(win) {
|
|
||||||
return win && win.document.readyState === 'complete';
|
|
||||||
};
|
|
||||||
|
|
||||||
return function(win) {
|
|
||||||
deferUntil(
|
|
||||||
canRegister.bind(null, win),
|
|
||||||
register.bind(this, win)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.contextMenu.unregister = function(win) {
|
|
||||||
if ( !this.menuItemId ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( vAPI.fennec ) {
|
|
||||||
// TODO
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var doc = win.document;
|
|
||||||
var menuitem = doc.getElementById(this.menuItemId);
|
|
||||||
|
|
||||||
// Not guarantee the menu item was actually registered.
|
|
||||||
if ( menuitem === null ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var contextMenu = menuitem.parentNode;
|
|
||||||
menuitem.removeEventListener('command', this.onCommand);
|
|
||||||
contextMenu.removeEventListener('popupshowing', this.displayMenuItem);
|
|
||||||
contextMenu.removeChild(menuitem);
|
|
||||||
};
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
vAPI.contextMenu.create = function(details, callback) {
|
|
||||||
this.menuItemId = details.id;
|
|
||||||
this.menuLabel = details.title;
|
|
||||||
this.contexts = details.contexts;
|
|
||||||
|
|
||||||
if ( Array.isArray(this.contexts) && this.contexts.length ) {
|
|
||||||
this.contexts = this.contexts.indexOf('all') === -1 ? this.contexts : null;
|
|
||||||
} else {
|
|
||||||
// default in Chrome
|
|
||||||
this.contexts = ['page'];
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onCommand = function() {
|
|
||||||
var gContextMenu = getOwnerWindow(this).gContextMenu;
|
var gContextMenu = getOwnerWindow(this).gContextMenu;
|
||||||
var details = {
|
var details = {
|
||||||
menuItemId: this.id
|
menuItemId: this.id
|
||||||
|
@ -3361,29 +3215,185 @@ vAPI.contextMenu.create = function(details, callback) {
|
||||||
details.linkUrl = gContextMenu.linkURL;
|
details.linkUrl = gContextMenu.linkURL;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(details, {
|
clientCallback(details, {
|
||||||
id: tabWatcher.tabIdFromTarget(gContextMenu.browser),
|
id: tabWatcher.tabIdFromTarget(gContextMenu.browser),
|
||||||
url: gContextMenu.browser.currentURI.asciiSpec
|
url: gContextMenu.browser.currentURI.asciiSpec
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
for ( var win of winWatcher.getWindows() ) {
|
var menuItemMatchesContext = function(contextMenu, clientEntry) {
|
||||||
this.register(win);
|
if ( !clientEntry.contexts ) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
for ( var context of clientEntry.contexts ) {
|
||||||
|
if ( context === 'all' ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
contextMap.hasOwnProperty(context) &&
|
||||||
|
contextMenu[contextMap[context]]
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
var onMenuShowing = function({target}) {
|
||||||
|
var doc = target.ownerDocument;
|
||||||
vAPI.contextMenu.remove = function() {
|
var gContextMenu = doc.defaultView.gContextMenu;
|
||||||
for ( var win of winWatcher.getWindows() ) {
|
if ( !gContextMenu.browser ) {
|
||||||
this.unregister(win);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.menuItemId = null;
|
// https://github.com/chrisaljoudi/uBlock/issues/105
|
||||||
this.menuLabel = null;
|
// TODO: Should the element picker works on any kind of pages?
|
||||||
this.contexts = null;
|
var currentURI = gContextMenu.browser.currentURI,
|
||||||
this.onCommand = null;
|
isHTTP = currentURI.schemeIs('http') || currentURI.schemeIs('https'),
|
||||||
};
|
layoutChanged = false,
|
||||||
|
contextMenu = doc.getElementById('contentAreaContextMenu'),
|
||||||
|
newEntries = clientEntries,
|
||||||
|
oldMenuitems = contextMenu.querySelectorAll('[data-uBlock0="menuitem"]'),
|
||||||
|
newMenuitems = [],
|
||||||
|
n = Math.max(clientEntries.length, oldMenuitems.length),
|
||||||
|
menuitem, newEntry;
|
||||||
|
for ( var i = 0; i < n; i++ ) {
|
||||||
|
menuitem = oldMenuitems[i];
|
||||||
|
newEntry = newEntries[i];
|
||||||
|
if ( menuitem && !newEntry ) {
|
||||||
|
menuitem.parentNode.removeChild(menuitem);
|
||||||
|
menuitem.removeEventListener('command', onCommand);
|
||||||
|
menuitem = null;
|
||||||
|
layoutChanged = true;
|
||||||
|
} else if ( !menuitem && newEntry ) {
|
||||||
|
menuitem = doc.createElement('menuitem');
|
||||||
|
menuitem.setAttribute('data-uBlock0', 'menuitem');
|
||||||
|
menuitem.addEventListener('command', onCommand);
|
||||||
|
}
|
||||||
|
if ( !menuitem ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( menuitem.id !== newEntry.id ) {
|
||||||
|
menuitem.setAttribute('id', newEntry.id);
|
||||||
|
menuitem.setAttribute('label', newEntry.title);
|
||||||
|
layoutChanged = true;
|
||||||
|
}
|
||||||
|
menuitem.setAttribute('hidden', !isHTTP || !menuItemMatchesContext(gContextMenu, newEntry));
|
||||||
|
newMenuitems.push(menuitem);
|
||||||
|
}
|
||||||
|
// No changes?
|
||||||
|
if ( layoutChanged === false ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// No entry: remove submenu if present.
|
||||||
|
var menu = contextMenu.querySelector('[data-uBlock0="menu"]');
|
||||||
|
if ( newMenuitems.length === 0 ) {
|
||||||
|
if ( menu !== null ) {
|
||||||
|
menu.parentNode.removeChild(menuitem);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Only one entry: no need for a submenu.
|
||||||
|
if ( newMenuitems.length === 1 ) {
|
||||||
|
if ( menu !== null ) {
|
||||||
|
menu.parentNode.removeChild(menu);
|
||||||
|
}
|
||||||
|
menuitem = newMenuitems[0];
|
||||||
|
menuitem.setAttribute('class', 'menuitem-iconic');
|
||||||
|
menuitem.setAttribute('image', vAPI.getURL('img/browsericons/icon16.svg'));
|
||||||
|
contextMenu.insertBefore(menuitem, doc.getElementById('inspect-separator'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// More than one entry: we need a submenu.
|
||||||
|
if ( menu === null ) {
|
||||||
|
menu = doc.createElement('menu');
|
||||||
|
menu.setAttribute('label', vAPI.app.name);
|
||||||
|
menu.setAttribute('data-uBlock0', 'menu');
|
||||||
|
menu.setAttribute('class', 'menu-iconic');
|
||||||
|
menu.setAttribute('image', vAPI.getURL('img/browsericons/icon16.svg'));
|
||||||
|
contextMenu.insertBefore(menu, doc.getElementById('inspect-separator'));
|
||||||
|
}
|
||||||
|
var menupopup = contextMenu.querySelector('[data-uBlock0="menupopup"]');
|
||||||
|
if ( menupopup === null ) {
|
||||||
|
menupopup = doc.createElement('menupopup');
|
||||||
|
menupopup.setAttribute('data-uBlock0', 'menupopup');
|
||||||
|
menu.appendChild(menupopup);
|
||||||
|
}
|
||||||
|
for ( i = 0; i < newMenuitems.length; i++ ) {
|
||||||
|
menuitem = newMenuitems[i];
|
||||||
|
menuitem.setAttribute('class', 'menuitem-non-iconic');
|
||||||
|
menuitem.removeAttribute('image');
|
||||||
|
menupopup.appendChild(menuitem);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://github.com/gorhill/uBlock/issues/906
|
||||||
|
// Be sure document.readyState is 'complete': it could happen at launch
|
||||||
|
// time that we are called by vAPI.contextMenu.create() directly before
|
||||||
|
// the environment is properly initialized.
|
||||||
|
var canRegister = function(win) {
|
||||||
|
return win && win.document.readyState === 'complete';
|
||||||
|
};
|
||||||
|
|
||||||
|
var register = function(window) {
|
||||||
|
if ( canRegister(window) !== true ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var contextMenu = window.document.getElementById('contentAreaContextMenu');
|
||||||
|
if ( contextMenu === null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
contextMenu.addEventListener('popupshowing', onMenuShowing);
|
||||||
|
};
|
||||||
|
|
||||||
|
var registerAsync = function(win) {
|
||||||
|
// TODO https://developer.mozilla.org/en-US/Add-ons/Firefox_for_Android/API/NativeWindow/contextmenus/add
|
||||||
|
// var nativeWindow = doc.defaultView.NativeWindow;
|
||||||
|
// contextId = nativeWindow.contextmenus.add(
|
||||||
|
// this.menuLabel,
|
||||||
|
// nativeWindow.contextmenus.linkOpenableContext,
|
||||||
|
// this.onCommand
|
||||||
|
// );
|
||||||
|
if ( vAPI.fennec ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deferUntil(
|
||||||
|
canRegister.bind(null, win),
|
||||||
|
register.bind(null, win)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
var unregister = function(win) {
|
||||||
|
// TODO
|
||||||
|
if ( vAPI.fennec ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var contextMenu = win.document.getElementById('contentAreaContextMenu');
|
||||||
|
if ( contextMenu !== null ) {
|
||||||
|
contextMenu.removeEventListener('popupshowing', onMenuShowing);
|
||||||
|
}
|
||||||
|
var menuitems = win.document.querySelectorAll('[data-uBlock0]'),
|
||||||
|
menuitem;
|
||||||
|
for ( var i = 0; i < menuitems.length; i++ ) {
|
||||||
|
menuitem = menuitems[i];
|
||||||
|
menuitem.parentNode.removeChild(menuitem);
|
||||||
|
menuitem.removeEventListener('command', onCommand);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var setEntries = function(entries, callback) {
|
||||||
|
clientEntries = entries || [];
|
||||||
|
clientCallback = callback || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
onMustUpdate: function() {},
|
||||||
|
register: registerAsync,
|
||||||
|
unregister: unregister,
|
||||||
|
setEntries: setEntries
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global addMessageListener, removeMessageListener, sendAsyncMessage, outerShutdown */
|
/* global HTMLDocument, XMLDocument,
|
||||||
|
addMessageListener, removeMessageListener, sendAsyncMessage, outerShutdown
|
||||||
|
*/
|
||||||
|
|
||||||
// For non background pages
|
// For non background pages
|
||||||
|
|
||||||
|
@ -29,6 +31,18 @@
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// https://github.com/chrisaljoudi/uBlock/issues/464
|
||||||
|
if ( document instanceof HTMLDocument === false ) {
|
||||||
|
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
||||||
|
// A XMLDocument can be a valid HTML document.
|
||||||
|
if (
|
||||||
|
document instanceof XMLDocument === false ||
|
||||||
|
document.createElement('div') instanceof HTMLDivElement === false
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Not all sandboxes are given an rpc function, so assign a dummy one if it is
|
// Not all sandboxes are given an rpc function, so assign a dummy one if it is
|
||||||
|
|
|
@ -77,19 +77,19 @@
|
||||||
},
|
},
|
||||||
"popupTipNoPopups":{
|
"popupTipNoPopups":{
|
||||||
"message":"Toggle the blocking of all popups for this site",
|
"message":"Toggle the blocking of all popups for this site",
|
||||||
"description":"English: Toggle the blocking of all popups for this site"
|
"description":"Tooltip for the no-popups per-site switch"
|
||||||
},
|
},
|
||||||
"popupTipNoStrictBlocking":{
|
"popupTipNoLargeMedia":{
|
||||||
"message":"Toggle strict blocking for this site",
|
"message":"Toggle the blocking of large media elements for this site",
|
||||||
"description":"English: Toggle strict blocking for this site"
|
"description":"Tooltip for the no-large-media per-site switch"
|
||||||
},
|
},
|
||||||
"popupTipNoCosmeticFiltering":{
|
"popupTipNoCosmeticFiltering":{
|
||||||
"message":"Toggle cosmetic filtering for this site",
|
"message":"Toggle cosmetic filtering for this site",
|
||||||
"description":"English: Toggle cosmetic filtering for this site"
|
"description":"Tooltip for the no-cosmetic-filtering per-site switch"
|
||||||
},
|
},
|
||||||
"popupTipNoRemoteFonts":{
|
"popupTipNoRemoteFonts":{
|
||||||
"message":"Toggle the blocking of remote fonts for this site",
|
"message":"Toggle the blocking of remote fonts for this site",
|
||||||
"description":"English: Toggle the blocking of remote fonts for this site"
|
"description":"Tooltip for the no-remote-fonts per-site switch"
|
||||||
},
|
},
|
||||||
"popupTipGlobalRules":{
|
"popupTipGlobalRules":{
|
||||||
"message":"Global rules: this column is for rules which apply to all sites.",
|
"message":"Global rules: this column is for rules which apply to all sites.",
|
||||||
|
@ -215,9 +215,25 @@
|
||||||
"message":"Prevent WebRTC from leaking local IP addresses",
|
"message":"Prevent WebRTC from leaking local IP addresses",
|
||||||
"description":"English: "
|
"description":"English: "
|
||||||
},
|
},
|
||||||
"settingsExperimentalPrompt":{
|
"settingPerSiteSwitchGroup":{
|
||||||
"message":"Enable experimental features (<a href='https:\/\/github.com\/gorhill\/uBlock\/wiki\/Experimental-features'>About<\/a>)",
|
"message":"Default behavior",
|
||||||
"description":"English: Enable experimental features"
|
"description": ""
|
||||||
|
},
|
||||||
|
"settingPerSiteSwitchGroupSynopsis":{
|
||||||
|
"message":"These default behaviors can be overriden on a per-site basis",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"settingsNoCosmeticFilteringPrompt":{
|
||||||
|
"message":"Disable cosmetic filtering",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"settingsNoLargeMediaPrompt":{
|
||||||
|
"message":"Block media elements larger than {{input:number}} kB",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"settingsNoRemoteFontsPrompt":{
|
||||||
|
"message":"Block remote fonts",
|
||||||
|
"description": ""
|
||||||
},
|
},
|
||||||
"settingsStorageUsed":{
|
"settingsStorageUsed":{
|
||||||
"message":"Storage used: {{value}} bytes",
|
"message":"Storage used: {{value}} bytes",
|
||||||
|
@ -233,23 +249,23 @@
|
||||||
},
|
},
|
||||||
"3pListsOfBlockedHostsPrompt":{
|
"3pListsOfBlockedHostsPrompt":{
|
||||||
"message":"{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:",
|
"message":"{{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:",
|
||||||
"description":"English: {{netFilterCount}} network filters + {{cosmeticFilterCount}} cosmetic filters from:"
|
"description":"Appears at the top of the _3rd-party filters_ pane"
|
||||||
},
|
},
|
||||||
"3pListsOfBlockedHostsPerListStats":{
|
"3pListsOfBlockedHostsPerListStats":{
|
||||||
"message":"{{used}} used out of {{total}}",
|
"message":"{{used}} used out of {{total}}",
|
||||||
"description":"English: {{used}} used out of {{total}}"
|
"description":"Appears aside each filter list in the _3rd-party filters_ pane"
|
||||||
},
|
},
|
||||||
"3pAutoUpdatePrompt1":{
|
"3pAutoUpdatePrompt1":{
|
||||||
"message":"Auto-update filter lists.",
|
"message":"Auto-update filter lists.",
|
||||||
"description":"English: Auto-update filter lists."
|
"description":"A checkbox in the _3rd-party filters_ pane"
|
||||||
},
|
},
|
||||||
"3pUpdateNow":{
|
"3pUpdateNow":{
|
||||||
"message":"Update now",
|
"message":"Update now",
|
||||||
"description":"English: Update now"
|
"description":"A button in the in the _3rd-party filters_ pane"
|
||||||
},
|
},
|
||||||
"3pPurgeAll":{
|
"3pPurgeAll":{
|
||||||
"message":"Purge all caches",
|
"message":"Purge all caches",
|
||||||
"description":"English: Purge all caches"
|
"description":"A button in the in the _3rd-party filters_ pane"
|
||||||
},
|
},
|
||||||
"3pParseAllABPHideFiltersPrompt1":{
|
"3pParseAllABPHideFiltersPrompt1":{
|
||||||
"message":"Parse and enforce cosmetic filters.",
|
"message":"Parse and enforce cosmetic filters.",
|
||||||
|
@ -651,6 +667,10 @@
|
||||||
"message": "bytes",
|
"message": "bytes",
|
||||||
"description": ""
|
"description": ""
|
||||||
},
|
},
|
||||||
|
"contextMenuTemporarilyAllowLargeMediaElements": {
|
||||||
|
"message": "Temporarily allow large media elements",
|
||||||
|
"description": "A context menu entry, present when large media elements have been blocked on the current site"
|
||||||
|
},
|
||||||
"dummy":{
|
"dummy":{
|
||||||
"message":"This entry must be the last one",
|
"message":"This entry must be the last one",
|
||||||
"description":"so we dont need to deal with comma for last entry"
|
"description":"so we dont need to deal with comma for last entry"
|
||||||
|
|
|
@ -34,10 +34,17 @@ div > p:first-child {
|
||||||
div > p:last-child {
|
div > p:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
input[type="number"] {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
.para {
|
.para {
|
||||||
width: 40em;
|
width: 40em;
|
||||||
}
|
}
|
||||||
|
.synopsis {
|
||||||
|
font-size: small;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
.whatisthis {
|
.whatisthis {
|
||||||
margin: 0 0 0 8px;
|
margin: 0 0 0 8px;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
|
@ -176,7 +176,7 @@ body.off #switch .fa {
|
||||||
#extraTools > span {
|
#extraTools > span {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
margin: 0 0.4em;
|
margin: 0 0.5em;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
#extraTools > span > span.badge {
|
#extraTools > span > span.badge {
|
||||||
|
|
|
@ -61,6 +61,7 @@ return {
|
||||||
externalLists: defaultExternalLists,
|
externalLists: defaultExternalLists,
|
||||||
firewallPaneMinimized: true,
|
firewallPaneMinimized: true,
|
||||||
hyperlinkAuditingDisabled: true,
|
hyperlinkAuditingDisabled: true,
|
||||||
|
largeMediaSize: 50,
|
||||||
parseAllABPHideFilters: true,
|
parseAllABPHideFilters: true,
|
||||||
prefetchingDisabled: true,
|
prefetchingDisabled: true,
|
||||||
requestLogMaxEntries: 1000,
|
requestLogMaxEntries: 1000,
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Injected into content pages
|
// Injected into content pages
|
||||||
|
@ -31,18 +29,6 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// I've seen this happens on Firefox
|
// I've seen this happens on Firefox
|
||||||
if ( window.location === null ) {
|
if ( window.location === null ) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* jshint multistr: true */
|
/* jshint multistr: true */
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -34,18 +33,6 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can happen
|
// This can happen
|
||||||
if ( typeof vAPI !== 'object' ) {
|
if ( typeof vAPI !== 'object' ) {
|
||||||
//console.debug('contentscript-start.js > vAPI not found');
|
//console.debug('contentscript-start.js > vAPI not found');
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
µBlock - a browser extension to block requests.
|
uBlock Origin - a browser extension to block requests.
|
||||||
Copyright (C) 2014 Raymond Hill
|
Copyright (C) 2014-2015 Raymond Hill
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,26 +19,19 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, µBlock */
|
/******************************************************************************/
|
||||||
|
|
||||||
|
µBlock.contextMenu = (function() {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// New namespace
|
|
||||||
|
|
||||||
µBlock.contextMenu = (function() {
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var µb = µBlock;
|
var µb = µBlock;
|
||||||
var enabled = false;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var onContextMenuClicked = function(details, tab) {
|
var onBlockElement = function(details, tab) {
|
||||||
if ( details.menuItemId !== 'blockElement' ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( tab === undefined ) {
|
if ( tab === undefined ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -69,29 +62,90 @@ var onContextMenuClicked = function(details, tab) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var toggleMenu = function(on) {
|
var onTemporarilyAllowLargeMediaElements = function(details, tab) {
|
||||||
// This needs to be local scope: we can't reuse it for more than one
|
if ( tab === undefined ) {
|
||||||
// menu creation call.
|
return;
|
||||||
var menuCreateDetails = {
|
}
|
||||||
id: 'blockElement',
|
var pageStore = µb.pageStoreFromTabId(tab.id);
|
||||||
title: vAPI.i18n('pickerContextMenuEntry'),
|
if ( pageStore === null ) {
|
||||||
contexts: ['page', 'editable', 'frame', 'link', 'image', 'video'],
|
return;
|
||||||
documentUrlPatterns: ['https://*/*', 'http://*/*']
|
}
|
||||||
};
|
pageStore.temporarilyAllowLargeMediaElements();
|
||||||
|
};
|
||||||
|
|
||||||
if ( on === true && enabled === false ) {
|
/******************************************************************************/
|
||||||
vAPI.contextMenu.create(menuCreateDetails, onContextMenuClicked);
|
|
||||||
enabled = true;
|
var onEntryClicked = function(details, tab) {
|
||||||
} else if ( on !== true && enabled === true ) {
|
if ( details.menuItemId === 'uBlock0-blockElement' ) {
|
||||||
vAPI.contextMenu.remove();
|
return onBlockElement(details, tab);
|
||||||
enabled = false;
|
}
|
||||||
|
if ( details.menuItemId === 'uBlock0-temporarilyAllowLargeMediaElements' ) {
|
||||||
|
return onTemporarilyAllowLargeMediaElements(details, tab);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var menuEntries = [
|
||||||
|
{
|
||||||
|
id: 'uBlock0-blockElement',
|
||||||
|
title: vAPI.i18n('pickerContextMenuEntry'),
|
||||||
|
contexts: ['all'],
|
||||||
|
documentUrlPatterns: ['https://*/*', 'http://*/*']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'uBlock0-temporarilyAllowLargeMediaElements',
|
||||||
|
title: vAPI.i18n('contextMenuTemporarilyAllowLargeMediaElements'),
|
||||||
|
contexts: ['all'],
|
||||||
|
documentUrlPatterns: ['https://*/*', 'http://*/*']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var update = function(tabId) {
|
||||||
|
var newBits = 0;
|
||||||
|
if ( µb.userSettings.contextMenuEnabled && tabId !== null ) {
|
||||||
|
var pageStore = µb.pageStoreFromTabId(tabId);
|
||||||
|
if ( pageStore ) {
|
||||||
|
newBits |= 0x01;
|
||||||
|
if ( pageStore.largeMediaCount !== 0 ) {
|
||||||
|
newBits |= 0x02;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( newBits === currentBits ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentBits = newBits;
|
||||||
|
var usedEntries = [];
|
||||||
|
if ( newBits & 0x01 ) {
|
||||||
|
usedEntries.push(menuEntries[0]);
|
||||||
|
}
|
||||||
|
if ( newBits & 0x02 ) {
|
||||||
|
usedEntries.push(menuEntries[1]);
|
||||||
|
}
|
||||||
|
vAPI.contextMenu.setEntries(usedEntries, onEntryClicked);
|
||||||
|
};
|
||||||
|
|
||||||
|
var currentBits = 0;
|
||||||
|
|
||||||
|
vAPI.contextMenu.onMustUpdate = update;
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
return {
|
return {
|
||||||
toggle: toggleMenu
|
update: function(tabId) {
|
||||||
|
if ( µb.userSettings.contextMenuEnabled && tabId === undefined ) {
|
||||||
|
vAPI.tabs.get(null, function(tab) {
|
||||||
|
if ( tab ) {
|
||||||
|
update(tab.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
update(tabId);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -40,7 +40,8 @@ var switchBitOffsets = {
|
||||||
'no-strict-blocking': 0,
|
'no-strict-blocking': 0,
|
||||||
'no-popups': 2,
|
'no-popups': 2,
|
||||||
'no-cosmetic-filtering': 4,
|
'no-cosmetic-filtering': 4,
|
||||||
'no-remote-fonts': 6
|
'no-remote-fonts': 6,
|
||||||
|
'no-large-media': 8
|
||||||
};
|
};
|
||||||
|
|
||||||
var fromLegacySwitchNames = {
|
var fromLegacySwitchNames = {
|
||||||
|
|
|
@ -128,10 +128,6 @@ var onMessage = function(request, sender, callback) {
|
||||||
response = getDomainNames(request.targets);
|
response = getDomainNames(request.targets);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'getUserSettings':
|
|
||||||
response = µb.userSettings;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'launchElementPicker':
|
case 'launchElementPicker':
|
||||||
// Launched from some auxiliary pages, clear context menu coords.
|
// Launched from some auxiliary pages, clear context menu coords.
|
||||||
µb.mouseX = µb.mouseY = -1;
|
µb.mouseX = µb.mouseY = -1;
|
||||||
|
@ -277,6 +273,7 @@ var getFirewallRules = function(srcHostname, desHostnames) {
|
||||||
|
|
||||||
var popupDataFromTabId = function(tabId, tabTitle) {
|
var popupDataFromTabId = function(tabId, tabTitle) {
|
||||||
var tabContext = µb.tabContextManager.mustLookup(tabId);
|
var tabContext = µb.tabContextManager.mustLookup(tabId);
|
||||||
|
var rootHostname = tabContext.rootHostname;
|
||||||
var r = {
|
var r = {
|
||||||
advancedUserEnabled: µb.userSettings.advancedUserEnabled,
|
advancedUserEnabled: µb.userSettings.advancedUserEnabled,
|
||||||
appName: vAPI.app.name,
|
appName: vAPI.app.name,
|
||||||
|
@ -290,7 +287,7 @@ var popupDataFromTabId = function(tabId, tabTitle) {
|
||||||
netFilteringSwitch: false,
|
netFilteringSwitch: false,
|
||||||
rawURL: tabContext.rawURL,
|
rawURL: tabContext.rawURL,
|
||||||
pageURL: tabContext.normalURL,
|
pageURL: tabContext.normalURL,
|
||||||
pageHostname: tabContext.rootHostname,
|
pageHostname: rootHostname,
|
||||||
pageDomain: tabContext.rootDomain,
|
pageDomain: tabContext.rootDomain,
|
||||||
pageAllowedRequestCount: 0,
|
pageAllowedRequestCount: 0,
|
||||||
pageBlockedRequestCount: 0,
|
pageBlockedRequestCount: 0,
|
||||||
|
@ -307,21 +304,22 @@ var popupDataFromTabId = function(tabId, tabTitle) {
|
||||||
r.netFilteringSwitch = pageStore.getNetFilteringSwitch();
|
r.netFilteringSwitch = pageStore.getNetFilteringSwitch();
|
||||||
r.hostnameDict = getHostnameDict(pageStore.hostnameToCountMap);
|
r.hostnameDict = getHostnameDict(pageStore.hostnameToCountMap);
|
||||||
r.contentLastModified = pageStore.contentLastModified;
|
r.contentLastModified = pageStore.contentLastModified;
|
||||||
r.firewallRules = getFirewallRules(tabContext.rootHostname, r.hostnameDict);
|
r.firewallRules = getFirewallRules(rootHostname, r.hostnameDict);
|
||||||
r.canElementPicker = tabContext.rootHostname.indexOf('.') !== -1;
|
r.canElementPicker = rootHostname.indexOf('.') !== -1;
|
||||||
r.noPopups = µb.hnSwitches.evaluateZ('no-popups', tabContext.rootHostname);
|
r.noPopups = µb.hnSwitches.evaluateZ('no-popups', rootHostname);
|
||||||
r.noStrictBlocking = µb.hnSwitches.evaluateZ('no-strict-blocking', tabContext.rootHostname);
|
|
||||||
r.noCosmeticFiltering = µb.hnSwitches.evaluateZ('no-cosmetic-filtering', tabContext.rootHostname);
|
|
||||||
r.noRemoteFonts = µb.hnSwitches.evaluateZ('no-remote-fonts', tabContext.rootHostname);
|
|
||||||
r.remoteFontCount = pageStore.remoteFontCount;
|
|
||||||
r.popupBlockedCount = pageStore.popupBlockedCount;
|
r.popupBlockedCount = pageStore.popupBlockedCount;
|
||||||
|
r.noCosmeticFiltering = µb.hnSwitches.evaluateZ('no-cosmetic-filtering', rootHostname);
|
||||||
|
r.noLargeMedia = µb.hnSwitches.evaluateZ('no-large-media', rootHostname);
|
||||||
|
r.largeMediaCount = pageStore.largeMediaCount;
|
||||||
|
r.noRemoteFonts = µb.hnSwitches.evaluateZ('no-remote-fonts', rootHostname);
|
||||||
|
r.remoteFontCount = pageStore.remoteFontCount;
|
||||||
} else {
|
} else {
|
||||||
r.hostnameDict = {};
|
r.hostnameDict = {};
|
||||||
r.firewallRules = getFirewallRules();
|
r.firewallRules = getFirewallRules();
|
||||||
}
|
}
|
||||||
r.matrixIsDirty = !µb.sessionFirewall.hasSameRules(
|
r.matrixIsDirty = !µb.sessionFirewall.hasSameRules(
|
||||||
µb.permanentFirewall,
|
µb.permanentFirewall,
|
||||||
tabContext.rootHostname,
|
rootHostname,
|
||||||
r.hostnameDict
|
r.hostnameDict
|
||||||
);
|
);
|
||||||
return r;
|
return r;
|
||||||
|
@ -1342,48 +1340,6 @@ vAPI.messaging.listen('logger-ui.js', onMessage);
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// subscriber.js
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
var onMessage = function(request, sender, callback) {
|
|
||||||
// Async
|
|
||||||
switch ( request.what ) {
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync
|
|
||||||
var response;
|
|
||||||
|
|
||||||
switch ( request.what ) {
|
|
||||||
case 'subscriberData':
|
|
||||||
response = {
|
|
||||||
confirmStr: vAPI.i18n('subscriberConfirm'),
|
|
||||||
externalLists: µBlock.userSettings.externalLists
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return vAPI.messaging.UNHANDLED;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(response);
|
|
||||||
};
|
|
||||||
|
|
||||||
vAPI.messaging.listen('subscriber.js', onMessage);
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// document-blocked.js
|
// document-blocked.js
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -1461,6 +1417,7 @@ var logCosmeticFilters = function(tabId, details) {
|
||||||
|
|
||||||
var onMessage = function(request, sender, callback) {
|
var onMessage = function(request, sender, callback) {
|
||||||
var tabId = sender && sender.tab ? sender.tab.id : 0;
|
var tabId = sender && sender.tab ? sender.tab.id : 0;
|
||||||
|
var pageStore = µb.pageStoreFromTabId(tabId);
|
||||||
|
|
||||||
// Async
|
// Async
|
||||||
switch ( request.what ) {
|
switch ( request.what ) {
|
||||||
|
@ -1473,8 +1430,7 @@ var onMessage = function(request, sender, callback) {
|
||||||
|
|
||||||
switch ( request.what ) {
|
switch ( request.what ) {
|
||||||
case 'liveCosmeticFilteringData':
|
case 'liveCosmeticFilteringData':
|
||||||
var pageStore = µb.pageStoreFromTabId(tabId);
|
if ( pageStore !== null ) {
|
||||||
if ( pageStore ) {
|
|
||||||
pageStore.hiddenElementCount = request.filteredElementCount;
|
pageStore.hiddenElementCount = request.filteredElementCount;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1483,6 +1439,19 @@ var onMessage = function(request, sender, callback) {
|
||||||
logCosmeticFilters(tabId, request);
|
logCosmeticFilters(tabId, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'temporarilyAllowLargeMediaElement':
|
||||||
|
if ( pageStore !== null ) {
|
||||||
|
pageStore.allowLargeMediaElementsUntil = Date.now() + 2000;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'subscriberData':
|
||||||
|
response = {
|
||||||
|
confirmStr: vAPI.i18n('subscriberConfirm'),
|
||||||
|
externalLists: µBlock.userSettings.externalLists
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return vAPI.messaging.UNHANDLED;
|
return vAPI.messaging.UNHANDLED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,6 +294,16 @@ PageStore.factory = function(tabId) {
|
||||||
PageStore.prototype.init = function(tabId) {
|
PageStore.prototype.init = function(tabId) {
|
||||||
var tabContext = µb.tabContextManager.mustLookup(tabId);
|
var tabContext = µb.tabContextManager.mustLookup(tabId);
|
||||||
this.tabId = tabId;
|
this.tabId = tabId;
|
||||||
|
|
||||||
|
// If we are navigating from-to same site, remember whether large
|
||||||
|
// media elements were temporarily allowed.
|
||||||
|
if (
|
||||||
|
typeof this.allowLargeMediaElementsUntil !== 'number' ||
|
||||||
|
tabContext.rootHostname !== this.tabHostname
|
||||||
|
) {
|
||||||
|
this.allowLargeMediaElementsUntil = 0;
|
||||||
|
}
|
||||||
|
|
||||||
this.tabHostname = tabContext.rootHostname;
|
this.tabHostname = tabContext.rootHostname;
|
||||||
this.title = tabContext.rawURL;
|
this.title = tabContext.rawURL;
|
||||||
this.rawURL = tabContext.rawURL;
|
this.rawURL = tabContext.rawURL;
|
||||||
|
@ -305,6 +315,8 @@ PageStore.prototype.init = function(tabId) {
|
||||||
this.hiddenElementCount = ''; // Empty string means "unknown"
|
this.hiddenElementCount = ''; // Empty string means "unknown"
|
||||||
this.remoteFontCount = 0;
|
this.remoteFontCount = 0;
|
||||||
this.popupBlockedCount = 0;
|
this.popupBlockedCount = 0;
|
||||||
|
this.largeMediaCount = 0;
|
||||||
|
this.largeMediaTimer = null;
|
||||||
this.netFilteringCache = NetFilteringResultCache.factory();
|
this.netFilteringCache = NetFilteringResultCache.factory();
|
||||||
|
|
||||||
// Support `elemhide` filter option. Called at this point so the required
|
// Support `elemhide` filter option. Called at this point so the required
|
||||||
|
@ -354,6 +366,10 @@ PageStore.prototype.reuse = function(context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A new page is completely reloaded from scratch, reset all.
|
// A new page is completely reloaded from scratch, reset all.
|
||||||
|
if ( this.largeMediaTimer !== null ) {
|
||||||
|
clearTimeout(this.largeMediaTimer);
|
||||||
|
this.largeMediaTimer = null;
|
||||||
|
}
|
||||||
this.disposeFrameStores();
|
this.disposeFrameStores();
|
||||||
this.netFilteringCache = this.netFilteringCache.dispose();
|
this.netFilteringCache = this.netFilteringCache.dispose();
|
||||||
this.init(this.tabId);
|
this.init(this.tabId);
|
||||||
|
@ -373,6 +389,11 @@ PageStore.prototype.dispose = function() {
|
||||||
this.title = '';
|
this.title = '';
|
||||||
this.rawURL = '';
|
this.rawURL = '';
|
||||||
this.hostnameToCountMap = null;
|
this.hostnameToCountMap = null;
|
||||||
|
this.allowLargeMediaElementsUntil = 0;
|
||||||
|
if ( this.largeMediaTimer !== null ) {
|
||||||
|
clearTimeout(this.largeMediaTimer);
|
||||||
|
this.largeMediaTimer = null;
|
||||||
|
}
|
||||||
this.disposeFrameStores();
|
this.disposeFrameStores();
|
||||||
this.netFilteringCache = this.netFilteringCache.dispose();
|
this.netFilteringCache = this.netFilteringCache.dispose();
|
||||||
if ( pageStoreJunkyard.length < pageStoreJunkyardMax ) {
|
if ( pageStoreJunkyard.length < pageStoreJunkyardMax ) {
|
||||||
|
@ -469,6 +490,32 @@ PageStore.prototype.toggleNetFilteringSwitch = function(url, scope, state) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
PageStore.prototype.logLargeMedia = (function() {
|
||||||
|
var injectScript = function() {
|
||||||
|
this.largeMediaTimer = null;
|
||||||
|
µb.scriptlets.injectDeep(
|
||||||
|
this.tabId,
|
||||||
|
'load-large-media-interactive'
|
||||||
|
);
|
||||||
|
µb.contextMenu.update(this.tabId);
|
||||||
|
};
|
||||||
|
return function() {
|
||||||
|
this.largeMediaCount += 1;
|
||||||
|
if ( this.largeMediaTimer === null ) {
|
||||||
|
this.largeMediaTimer = vAPI.setTimeout(injectScript.bind(this), 500);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
PageStore.prototype.temporarilyAllowLargeMediaElements = function() {
|
||||||
|
this.largeMediaCount = 0;
|
||||||
|
µb.contextMenu.update(this.tabId);
|
||||||
|
this.allowLargeMediaElementsUntil = Date.now() + 86400000;
|
||||||
|
µb.scriptlets.injectDeep(this.tabId, 'load-large-media-all');
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
PageStore.prototype.filterRequest = function(context) {
|
PageStore.prototype.filterRequest = function(context) {
|
||||||
var requestType = context.requestType;
|
var requestType = context.requestType;
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ var hashFromPopupData = function(reset) {
|
||||||
}
|
}
|
||||||
hasher.sort();
|
hasher.sort();
|
||||||
hasher.push(uDom('body').hasClass('off'));
|
hasher.push(uDom('body').hasClass('off'));
|
||||||
|
hasher.push(uDom.nodeFromId('no-large-media').classList.contains('on'));
|
||||||
hasher.push(uDom.nodeFromId('no-cosmetic-filtering').classList.contains('on'));
|
hasher.push(uDom.nodeFromId('no-cosmetic-filtering').classList.contains('on'));
|
||||||
hasher.push(uDom.nodeFromId('no-remote-fonts').classList.contains('on'));
|
hasher.push(uDom.nodeFromId('no-remote-fonts').classList.contains('on'));
|
||||||
|
|
||||||
|
@ -459,7 +460,7 @@ var renderPopup = function() {
|
||||||
|
|
||||||
// Extra tools
|
// Extra tools
|
||||||
uDom.nodeFromId('no-popups').classList.toggle('on', popupData.noPopups === true);
|
uDom.nodeFromId('no-popups').classList.toggle('on', popupData.noPopups === true);
|
||||||
uDom.nodeFromId('no-strict-blocking').classList.toggle('on', popupData.noStrictBlocking === true);
|
uDom.nodeFromId('no-large-media').classList.toggle('on', popupData.noLargeMedia === true);
|
||||||
uDom.nodeFromId('no-cosmetic-filtering').classList.toggle('on', popupData.noCosmeticFiltering === true);
|
uDom.nodeFromId('no-cosmetic-filtering').classList.toggle('on', popupData.noCosmeticFiltering === true);
|
||||||
uDom.nodeFromId('no-remote-fonts').classList.toggle('on', popupData.noRemoteFonts === true);
|
uDom.nodeFromId('no-remote-fonts').classList.toggle('on', popupData.noRemoteFonts === true);
|
||||||
|
|
||||||
|
@ -468,6 +469,11 @@ var renderPopup = function() {
|
||||||
uDom.nodeFromSelector('#no-popups > span.badge')
|
uDom.nodeFromSelector('#no-popups > span.badge')
|
||||||
.textContent = total ? total.toLocaleString() : '';
|
.textContent = total ? total.toLocaleString() : '';
|
||||||
|
|
||||||
|
// Report large media count on badge
|
||||||
|
total = popupData.largeMediaCount;
|
||||||
|
uDom.nodeFromSelector('#no-large-media > span.badge')
|
||||||
|
.textContent = total ? total.toLocaleString() : '';
|
||||||
|
|
||||||
// Report remote font count on badge
|
// Report remote font count on badge
|
||||||
total = popupData.remoteFontCount;
|
total = popupData.remoteFontCount;
|
||||||
uDom.nodeFromSelector('#no-remote-fonts > span.badge')
|
uDom.nodeFromSelector('#no-remote-fonts > span.badge')
|
||||||
|
@ -733,18 +739,18 @@ var revertFirewallRules = function() {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var toggleHostnameSwitch = function() {
|
var toggleHostnameSwitch = function(ev) {
|
||||||
var elem = uDom(this);
|
var target = ev.currentTarget;
|
||||||
var switchName = elem.attr('id');
|
var switchName = target.getAttribute('id');
|
||||||
if ( !switchName ) {
|
if ( !switchName ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
elem.toggleClass('on');
|
target.classList.toggle('on');
|
||||||
messager.send({
|
messager.send({
|
||||||
what: 'toggleHostnameSwitch',
|
what: 'toggleHostnameSwitch',
|
||||||
name: switchName,
|
name: switchName,
|
||||||
hostname: popupData.pageHostname,
|
hostname: popupData.pageHostname,
|
||||||
state: elem.hasClass('on'),
|
state: target.classList.contains('on'),
|
||||||
tabId: popupData.tabId
|
tabId: popupData.tabId
|
||||||
});
|
});
|
||||||
hashFromPopupData();
|
hashFromPopupData();
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -29,19 +27,6 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can happen
|
|
||||||
if ( typeof vAPI !== 'object' ) {
|
if ( typeof vAPI !== 'object' ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -29,21 +27,7 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can happen
|
|
||||||
if ( typeof vAPI !== 'object' ) {
|
if ( typeof vAPI !== 'object' ) {
|
||||||
//console.debug('cosmetic-off.js > no vAPI');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -29,21 +27,7 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can happen
|
|
||||||
if ( typeof vAPI !== 'object' ) {
|
if ( typeof vAPI !== 'object' ) {
|
||||||
//console.debug('cosmetic-on.js > no vAPI');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
@ -29,21 +27,7 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can happen
|
|
||||||
if ( typeof vAPI !== 'object' ) {
|
if ( typeof vAPI !== 'object' ) {
|
||||||
//console.debug('cosmetic-survey.js > vAPI not found');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global vAPI, HTMLDocument, XMLDocument */
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
@ -30,19 +28,6 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/464
|
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This can happen
|
|
||||||
if ( typeof vAPI !== 'object' ) {
|
if ( typeof vAPI !== 'object' ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* global self, vAPI, CSS, HTMLDocument, XMLDocument */
|
/* global CSS */
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -66,16 +66,16 @@
|
||||||
if (
|
if (
|
||||||
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
// If the character is in the range [\1-\1F] (U+0001 to U+001F) or is
|
||||||
// U+007F, […]
|
// U+007F, […]
|
||||||
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit == 0x007F ||
|
(codeUnit >= 0x0001 && codeUnit <= 0x001F) || codeUnit === 0x007F ||
|
||||||
// If the character is the first character and is in the range [0-9]
|
// If the character is the first character and is in the range [0-9]
|
||||||
// (U+0030 to U+0039), […]
|
// (U+0030 to U+0039), […]
|
||||||
(index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
(index === 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||
|
||||||
// If the character is the second character and is in the range [0-9]
|
// If the character is the second character and is in the range [0-9]
|
||||||
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
// (U+0030 to U+0039) and the first character is a `-` (U+002D), […]
|
||||||
(
|
(
|
||||||
index == 1 &&
|
index === 1 &&
|
||||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
codeUnit >= 0x0030 && codeUnit <= 0x0039 &&
|
||||||
firstCodeUnit == 0x002D
|
firstCodeUnit === 0x002D
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
// http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
|
// http://dev.w3.org/csswg/cssom/#escape-a-character-as-code-point
|
||||||
|
@ -89,8 +89,8 @@
|
||||||
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
// U+005A), or [a-z] (U+0061 to U+007A), […]
|
||||||
if (
|
if (
|
||||||
codeUnit >= 0x0080 ||
|
codeUnit >= 0x0080 ||
|
||||||
codeUnit == 0x002D ||
|
codeUnit === 0x002D ||
|
||||||
codeUnit == 0x005F ||
|
codeUnit === 0x005F ||
|
||||||
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
codeUnit >= 0x0030 && codeUnit <= 0x0039 ||
|
||||||
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
codeUnit >= 0x0041 && codeUnit <= 0x005A ||
|
||||||
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
codeUnit >= 0x0061 && codeUnit <= 0x007A
|
||||||
|
@ -120,20 +120,10 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// https://github.com/gorhill/uBlock/issues/464
|
if ( typeof vAPI !== 'object' ) {
|
||||||
if ( document instanceof HTMLDocument === false ) {
|
|
||||||
// https://github.com/chrisaljoudi/uBlock/issues/1528
|
|
||||||
// A XMLDocument can be a valid HTML document.
|
|
||||||
if (
|
|
||||||
document instanceof XMLDocument === false ||
|
|
||||||
document.createElement('div') instanceof HTMLDivElement === false
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// don't run in frames
|
// don't run in frames
|
||||||
if ( window.top !== window ) {
|
if ( window.top !== window ) {
|
||||||
return;
|
return;
|
||||||
|
|
69
src/js/scriptlets/load-large-media-all.js
Normal file
69
src/js/scriptlets/load-large-media-all.js
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
uBlock Origin - a browser extension to block requests.
|
||||||
|
Copyright (C) 2015 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/uBlock
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// For all media resources which have failed to load, trigger a reload.
|
||||||
|
|
||||||
|
var elems, i, elem, src;
|
||||||
|
|
||||||
|
// <audio> and <video> elements.
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
|
||||||
|
elems = document.querySelectorAll('audio,video');
|
||||||
|
i = elems.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
elem = elems[i];
|
||||||
|
if ( elem.error !== null ) {
|
||||||
|
elem.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <img> elements.
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
|
||||||
|
elems = document.querySelectorAll('img');
|
||||||
|
i = elems.length;
|
||||||
|
while ( i-- ) {
|
||||||
|
elem = elems[i];
|
||||||
|
if (
|
||||||
|
typeof elem.naturalWidth !== 'number' ||
|
||||||
|
elem.naturalWidth === 0 ||
|
||||||
|
typeof elem.naturalHeight !== 'number' ||
|
||||||
|
elem.naturalHeight === 0
|
||||||
|
) {
|
||||||
|
src = elem.getAttribute('src') || '';
|
||||||
|
elem.removeAttribute('src');
|
||||||
|
elem.setAttribute('src', src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
222
src/js/scriptlets/load-large-media-interactive.js
Normal file
222
src/js/scriptlets/load-large-media-interactive.js
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
|
||||||
|
uBlock Origin - a browser extension to block requests.
|
||||||
|
Copyright (C) 2015 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/uBlock
|
||||||
|
*/
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// This can happen
|
||||||
|
if ( typeof vAPI !== 'object' || vAPI.loadLargeMediaInteractive === true ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var largeMediaElementAttribute = 'data-' + vAPI.sessionId;
|
||||||
|
var largeMediaElementSelector =
|
||||||
|
':root audio[' + largeMediaElementAttribute + '],\n' +
|
||||||
|
':root img[' + largeMediaElementAttribute + '],\n' +
|
||||||
|
':root video[' + largeMediaElementAttribute + ']';
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var mediaNotLoaded = function(elem) {
|
||||||
|
var src = elem.getAttribute('src') || '';
|
||||||
|
if ( src === '' ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch ( elem.localName ) {
|
||||||
|
case 'audio':
|
||||||
|
case 'video':
|
||||||
|
return elem.error !== null;
|
||||||
|
case 'img':
|
||||||
|
return elem.offsetWidth !== 0 && elem.offsetHeight !== 0 &&
|
||||||
|
(elem.naturalWidth === 0 || elem.naturalHeight === 0);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// For all media resources which have failed to load, trigger a reload.
|
||||||
|
|
||||||
|
// <audio> and <video> elements.
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
|
||||||
|
var surveyMissingMediaElements = function() {
|
||||||
|
var largeMediaElementCount = 0;
|
||||||
|
var elems = document.querySelectorAll('audio,img,video');
|
||||||
|
var i = elems.length, elem;
|
||||||
|
while ( i-- ) {
|
||||||
|
elem = elems[i];
|
||||||
|
if ( mediaNotLoaded(elem) ) {
|
||||||
|
elem.setAttribute(largeMediaElementAttribute, '');
|
||||||
|
largeMediaElementCount += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return largeMediaElementCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( surveyMissingMediaElements() === 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vAPI.loadLargeMediaInteractive = true;
|
||||||
|
|
||||||
|
// Insert custom style tag.
|
||||||
|
var styleTag = document.createElement('style');
|
||||||
|
styleTag.setAttribute('type', 'text/css');
|
||||||
|
styleTag.textContent = [
|
||||||
|
largeMediaElementSelector + ' {',
|
||||||
|
'border: 1px dotted red !important;',
|
||||||
|
'box-sizing: border-box !important;',
|
||||||
|
'cursor: zoom-in !important;',
|
||||||
|
'display: inline-block;',
|
||||||
|
'font-size: 1em !important;',
|
||||||
|
'min-height: 1em !important;',
|
||||||
|
'min-width: 1em !important;',
|
||||||
|
'}'
|
||||||
|
].join('\n');
|
||||||
|
document.head.appendChild(styleTag);
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var messager = vAPI.messaging.channel('scriptlets');
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var stayOrLeave = (function() {
|
||||||
|
var timer = null;
|
||||||
|
|
||||||
|
var timeoutHandler = function(leaveNow) {
|
||||||
|
timer = null;
|
||||||
|
if ( leaveNow !== true ) {
|
||||||
|
if (
|
||||||
|
document.querySelector(largeMediaElementSelector) !== null ||
|
||||||
|
surveyMissingMediaElements() !== 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Leave
|
||||||
|
if ( styleTag !== null ) {
|
||||||
|
styleTag.parentNode.removeChild(styleTag);
|
||||||
|
styleTag = null;
|
||||||
|
}
|
||||||
|
vAPI.loadLargeMediaInteractive = false;
|
||||||
|
document.removeEventListener('error', onLoadError, true);
|
||||||
|
document.removeEventListener('click', onMouseClick, true);
|
||||||
|
if ( messager !== null ) {
|
||||||
|
messager.close();
|
||||||
|
messager = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return function(leaveNow) {
|
||||||
|
if ( timer !== null ) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
if ( leaveNow ) {
|
||||||
|
timeoutHandler(true);
|
||||||
|
} else {
|
||||||
|
timer = vAPI.setTimeout(timeoutHandler, 5000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var onMouseClick = function(ev) {
|
||||||
|
if ( ev.button !== 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var elem = ev.target;
|
||||||
|
if ( elem.matches(largeMediaElementSelector) === false ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( mediaNotLoaded(elem) === false ) {
|
||||||
|
elem.removeAttribute(largeMediaElementAttribute);
|
||||||
|
stayOrLeave();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var src = elem.getAttribute('src');
|
||||||
|
elem.removeAttribute('src');
|
||||||
|
|
||||||
|
var onLargeMediaElementAllowed = function() {
|
||||||
|
elem.setAttribute('src', src);
|
||||||
|
elem.removeAttribute(largeMediaElementAttribute);
|
||||||
|
stayOrLeave();
|
||||||
|
};
|
||||||
|
|
||||||
|
messager.send({
|
||||||
|
what: 'temporarilyAllowLargeMediaElement'
|
||||||
|
}, onLargeMediaElementAllowed);
|
||||||
|
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('click', onMouseClick, true);
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var onLoad = function(ev) {
|
||||||
|
var elem = ev.target;
|
||||||
|
if ( elem.hasAttribute(largeMediaElementAttribute) ) {
|
||||||
|
elem.removeAttribute(largeMediaElementAttribute);
|
||||||
|
stayOrLeave();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('load', onLoad, true);
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var onLoadError = function(ev) {
|
||||||
|
var elem = ev.target;
|
||||||
|
if ( mediaNotLoaded(elem) ) {
|
||||||
|
elem.setAttribute(largeMediaElementAttribute, '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener('error', onLoadError, true);
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
vAPI.shutdown.add(function() {
|
||||||
|
stayOrLeave(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******************************************************************************/
|
|
@ -52,14 +52,14 @@ if ( typeof vAPI !== 'object' ) {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
document.querySelector('a[href^="abp:"],a[href^="https://subscribe.adblockplus.org/?"]') === null &&
|
document.querySelector('a[href^="abp:"],a[href^="https://subscribe.adblockplus.org/?"]') === null &&
|
||||||
window.location.href.startsWith('https://github.com/gorhill/uBlock/wiki/Filter-lists-from-around-the-web') === false
|
window.location.href.lastIndexOf('https://github.com/gorhill/uBlock/wiki/Filter-lists-from-around-the-web', 0) !== 0
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
var messager = vAPI.messaging.channel('subscriber.js');
|
var messager = vAPI.messaging.channel('scriptlets');
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
|
@ -159,12 +159,26 @@ var changeUserSettings = function(name, value) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
var onInputChanged = function(ev) {
|
||||||
|
var input = ev.target;
|
||||||
|
var name = this.getAttribute('data-setting-name');
|
||||||
|
var value = input.value;
|
||||||
|
if ( name === 'largeMediaSize' ) {
|
||||||
|
value = Math.min(Math.max(Math.floor(parseInt(value, 10) || 0), 0), 1000000);
|
||||||
|
}
|
||||||
|
if ( value !== input.value ) {
|
||||||
|
input.value = value;
|
||||||
|
}
|
||||||
|
changeUserSettings(name, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
// TODO: use data-* to declare simple settings
|
// TODO: use data-* to declare simple settings
|
||||||
|
|
||||||
var onUserSettingsReceived = function(details) {
|
var onUserSettingsReceived = function(details) {
|
||||||
uDom('[data-setting-type="bool"]').forEach(function(uNode) {
|
uDom('[data-setting-type="bool"]').forEach(function(uNode) {
|
||||||
var input = uNode.nodeAt(0);
|
uNode.prop('checked', details[uNode.attr('data-setting-name')] === true)
|
||||||
uNode.prop('checked', details[input.getAttribute('data-setting-name')] === true)
|
|
||||||
.on('change', function() {
|
.on('change', function() {
|
||||||
changeUserSettings(
|
changeUserSettings(
|
||||||
this.getAttribute('data-setting-name'),
|
this.getAttribute('data-setting-name'),
|
||||||
|
@ -173,6 +187,15 @@ var onUserSettingsReceived = function(details) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
uDom('[data-setting-name="noLargeMedia"] ~ label:first-of-type > input[type="number"]')
|
||||||
|
.attr('data-setting-name', 'largeMediaSize')
|
||||||
|
.attr('data-setting-type', 'input');
|
||||||
|
|
||||||
|
uDom('[data-setting-type="input"]').forEach(function(uNode) {
|
||||||
|
uNode.val(details[uNode.attr('data-setting-name')])
|
||||||
|
.on('change', onInputChanged);
|
||||||
|
});
|
||||||
|
|
||||||
uDom('#export').on('click', exportToFile);
|
uDom('#export').on('click', exportToFile);
|
||||||
uDom('#import').on('click', startImportFilePicker);
|
uDom('#import').on('click', startImportFilePicker);
|
||||||
uDom('#reset').on('click', resetUserData);
|
uDom('#reset').on('click', resetUserData);
|
||||||
|
|
|
@ -76,7 +76,7 @@ var onAllReady = function() {
|
||||||
//quickProfiler.stop(0);
|
//quickProfiler.stop(0);
|
||||||
|
|
||||||
vAPI.onLoadAllCompleted();
|
vAPI.onLoadAllCompleted();
|
||||||
|
µb.contextMenu.update(null);
|
||||||
µb.firstInstall = false;
|
µb.firstInstall = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,7 +169,6 @@ var onUserSettingsReady = function(fetched) {
|
||||||
// Disabling local mirroring for the time being
|
// Disabling local mirroring for the time being
|
||||||
userSettings.experimentalEnabled = false;
|
userSettings.experimentalEnabled = false;
|
||||||
|
|
||||||
µb.contextMenu.toggle(userSettings.contextMenuEnabled);
|
|
||||||
vAPI.browserSettings.set({
|
vAPI.browserSettings.set({
|
||||||
'hyperlinkAuditing': !userSettings.hyperlinkAuditingDisabled,
|
'hyperlinkAuditing': !userSettings.hyperlinkAuditingDisabled,
|
||||||
'prefetching': !userSettings.prefetchingDisabled,
|
'prefetching': !userSettings.prefetchingDisabled,
|
||||||
|
|
|
@ -784,7 +784,7 @@ vAPI.tabs.registerListeners();
|
||||||
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
if ( vAPI.isBehindTheSceneTabId(tabId) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 500);
|
tabIdToTimer[tabId] = vAPI.setTimeout(updateBadge.bind(this, tabId), 666);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ var onBeforeRequest = function(details) {
|
||||||
tabId,
|
tabId,
|
||||||
'redirect',
|
'redirect',
|
||||||
'rr:' + µb.redirectEngine.resourceNameRegister,
|
'rr:' + µb.redirectEngine.resourceNameRegister,
|
||||||
'redirect',
|
requestType,
|
||||||
requestURL,
|
requestURL,
|
||||||
requestContext.rootHostname,
|
requestContext.rootHostname,
|
||||||
requestContext.pageHostname
|
requestContext.pageHostname
|
||||||
|
@ -336,7 +336,9 @@ var onBeforeBehindTheSceneRequest = function(details) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// To handle `inline-script`.
|
// To handle:
|
||||||
|
// - inline script tags
|
||||||
|
// - media elements larger than n kB
|
||||||
|
|
||||||
var onHeadersReceived = function(details) {
|
var onHeadersReceived = function(details) {
|
||||||
// Do not interfere with behind-the-scene requests.
|
// Do not interfere with behind-the-scene requests.
|
||||||
|
@ -354,6 +356,10 @@ var onHeadersReceived = function(details) {
|
||||||
if ( requestType === 'sub_frame' ) {
|
if ( requestType === 'sub_frame' ) {
|
||||||
return onFrameHeadersReceived(details);
|
return onFrameHeadersReceived(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( requestType === 'image' || requestType === 'media' ) {
|
||||||
|
return foilLargeMediaElement(details);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -449,6 +455,58 @@ var onFrameHeadersReceived = function(details) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
// https://github.com/gorhill/uBlock/issues/1163
|
||||||
|
// "Block elements by size"
|
||||||
|
|
||||||
|
var foilLargeMediaElement = function(details) {
|
||||||
|
var µb = µBlock;
|
||||||
|
var tabId = details.tabId;
|
||||||
|
var pageStore = µb.pageStoreFromTabId(tabId);
|
||||||
|
if ( pageStore === null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( pageStore.getNetFilteringSwitch() !== true ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( Date.now() < pageStore.allowLargeMediaElementsUntil ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( µb.hnSwitches.evaluateZ('no-large-media', pageStore.tabHostname) !== true ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Not all servers provide the Content-Length header: when this happens,
|
||||||
|
// assume the worse.
|
||||||
|
var contentLength = 1000000,
|
||||||
|
i = headerIndexFromName('content-length', details.responseHeaders);
|
||||||
|
if ( i !== -1 ) {
|
||||||
|
contentLength = parseInt(details.responseHeaders[i].value, 10);
|
||||||
|
if ( isNaN(contentLength) ) {
|
||||||
|
contentLength = 1000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( (contentLength >>> 10) < µb.userSettings.largeMediaSize ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pageStore.logLargeMedia();
|
||||||
|
|
||||||
|
if ( µb.logger.isEnabled() ) {
|
||||||
|
µb.logger.writeOne(
|
||||||
|
tabId,
|
||||||
|
'net',
|
||||||
|
µb.hnSwitches.toResultString(),
|
||||||
|
details.type,
|
||||||
|
details.url,
|
||||||
|
pageStore.tabHostname,
|
||||||
|
pageStore.tabHostname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { cancel: true };
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
var foilInlineScripts = function(headers) {
|
var foilInlineScripts = function(headers) {
|
||||||
// Below is copy-pasta from uMatrix's project.
|
// Below is copy-pasta from uMatrix's project.
|
||||||
|
|
||||||
|
@ -567,8 +625,10 @@ vAPI.net.onHeadersReceived = {
|
||||||
'https://*/*'
|
'https://*/*'
|
||||||
],
|
],
|
||||||
types: [
|
types: [
|
||||||
"main_frame",
|
'main_frame',
|
||||||
"sub_frame"
|
'sub_frame',
|
||||||
|
'image',
|
||||||
|
'media'
|
||||||
],
|
],
|
||||||
extra: [ 'blocking', 'responseHeaders' ],
|
extra: [ 'blocking', 'responseHeaders' ],
|
||||||
callback: onHeadersReceived
|
callback: onHeadersReceived
|
||||||
|
|
|
@ -234,34 +234,44 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// Return all settings if none specified.
|
|
||||||
|
|
||||||
µBlock.changeUserSettings = function(name, value) {
|
µBlock.changeUserSettings = function(name, value) {
|
||||||
|
var us = this.userSettings;
|
||||||
|
|
||||||
|
// Return all settings if none specified.
|
||||||
if ( name === undefined ) {
|
if ( name === undefined ) {
|
||||||
return this.userSettings;
|
us = JSON.parse(JSON.stringify(us));
|
||||||
|
us.noCosmeticFiltering = this.hnSwitches.evaluate('no-cosmetic-filtering', '*') === 1;
|
||||||
|
us.noLargeMedia = this.hnSwitches.evaluate('no-large-media', '*') === 1;
|
||||||
|
us.noRemoteFonts = this.hnSwitches.evaluate('no-remote-fonts', '*') === 1;
|
||||||
|
return us;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( typeof name !== 'string' || name === '' ) {
|
if ( typeof name !== 'string' || name === '' ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not allow an unknown user setting to be created
|
|
||||||
if ( this.userSettings[name] === undefined ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( value === undefined ) {
|
if ( value === undefined ) {
|
||||||
return this.userSettings[name];
|
return us[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-change
|
// Pre-change
|
||||||
switch ( name ) {
|
switch ( name ) {
|
||||||
|
case 'largeMediaSize':
|
||||||
|
if ( typeof value !== 'number' ) {
|
||||||
|
value = parseInt(value, 10) || 0;
|
||||||
|
}
|
||||||
|
value = Math.ceil(Math.max(value, 0));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change
|
// Change -- but only if the user setting actually exists.
|
||||||
this.userSettings[name] = value;
|
var mustSave = us.hasOwnProperty(name) &&
|
||||||
|
value !== us[name];
|
||||||
|
if ( mustSave ) {
|
||||||
|
us[name] = value;
|
||||||
|
}
|
||||||
|
|
||||||
// Post-change
|
// Post-change
|
||||||
switch ( name ) {
|
switch ( name ) {
|
||||||
|
@ -271,13 +281,28 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'contextMenuEnabled':
|
case 'contextMenuEnabled':
|
||||||
this.contextMenu.toggle(value);
|
this.contextMenu.update(null);
|
||||||
break;
|
break;
|
||||||
case 'experimentalEnabled':
|
case 'experimentalEnabled':
|
||||||
break;
|
break;
|
||||||
case 'hyperlinkAuditingDisabled':
|
case 'hyperlinkAuditingDisabled':
|
||||||
vAPI.browserSettings.set({ 'hyperlinkAuditing': !value });
|
vAPI.browserSettings.set({ 'hyperlinkAuditing': !value });
|
||||||
break;
|
break;
|
||||||
|
case 'noCosmeticFiltering':
|
||||||
|
if ( this.hnSwitches.toggle('no-cosmetic-filtering', '*', value ? 1 : 0) ) {
|
||||||
|
this.saveHostnameSwitches();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'noLargeMedia':
|
||||||
|
if ( this.hnSwitches.toggle('no-large-media', '*', value ? 1 : 0) ) {
|
||||||
|
this.saveHostnameSwitches();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'noRemoteFonts':
|
||||||
|
if ( this.hnSwitches.toggle('no-remote-fonts', '*', value ? 1 : 0) ) {
|
||||||
|
this.saveHostnameSwitches();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'prefetchingDisabled':
|
case 'prefetchingDisabled':
|
||||||
vAPI.browserSettings.set({ 'prefetching': !value });
|
vAPI.browserSettings.set({ 'prefetching': !value });
|
||||||
break;
|
break;
|
||||||
|
@ -288,7 +313,9 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( mustSave ) {
|
||||||
this.saveUserSettings();
|
this.saveUserSettings();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -379,16 +406,22 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take action if needed
|
// Take action if needed
|
||||||
if ( details.name === 'no-cosmetic-filtering' ) {
|
switch ( details.name ) {
|
||||||
|
case 'no-cosmetic-filtering':
|
||||||
this.scriptlets.injectDeep(
|
this.scriptlets.injectDeep(
|
||||||
details.tabId,
|
details.tabId,
|
||||||
details.state ? 'cosmetic-off' : 'cosmetic-on'
|
details.state ? 'cosmetic-off' : 'cosmetic-on'
|
||||||
);
|
);
|
||||||
return;
|
break;
|
||||||
|
case 'no-large-media':
|
||||||
|
if ( details.state === false ) {
|
||||||
|
var pageStore = this.pageStoreFromTabId(details.tabId);
|
||||||
|
if ( pageStore !== null ) {
|
||||||
|
pageStore.temporarilyAllowLargeMediaElements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whatever else
|
|
||||||
// ...
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
<p class="statValue" id="popupHitDomainCount"> </p>
|
<p class="statValue" id="popupHitDomainCount"> </p>
|
||||||
<div id="extraTools">
|
<div id="extraTools">
|
||||||
<span id="no-popups" class="hnSwitch fa" data-i18n-tip="popupTipNoPopups"><span class="badge"></span><span></span></span>
|
<span id="no-popups" class="hnSwitch fa" data-i18n-tip="popupTipNoPopups"><span class="badge"></span><span></span></span>
|
||||||
<span id="no-strict-blocking" class="hnSwitch fa" data-i18n-tip="popupTipNoStrictBlocking"><span></span></span>
|
<span id="no-large-media" class="hnSwitch fa" data-i18n-tip="popupTipNoLargeMedia"><span class="badge"></span><span></span></span>
|
||||||
<span id="no-cosmetic-filtering" class="hnSwitch fa" data-i18n-tip="popupTipNoCosmeticFiltering"><span class="badge"></span><span></span></span>
|
<span id="no-cosmetic-filtering" class="hnSwitch fa" data-i18n-tip="popupTipNoCosmeticFiltering"><span class="badge"></span><span></span></span>
|
||||||
<span id="no-remote-fonts" class="hnSwitch fa" data-i18n-tip="popupTipNoRemoteFonts"><span class="badge"></span><span></span></span>
|
<span id="no-remote-fonts" class="hnSwitch fa" data-i18n-tip="popupTipNoRemoteFonts"><span class="badge"></span><span></span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
<li><input id="hyperlink-auditing-disabled" type="checkbox" data-setting-name="hyperlinkAuditingDisabled" data-setting-type="bool"><label data-i18n="settingsHyperlinkAuditingDisabledPrompt" for="hyperlink-auditing-disabled"></label> <a class="fa info" href="http://www.wilderssecurity.com/threads/hyperlink-auditing-aka-a-ping-and-beacon-aka-navigator-sendbeacon.364904/" target="_blank"></a>
|
<li><input id="hyperlink-auditing-disabled" type="checkbox" data-setting-name="hyperlinkAuditingDisabled" data-setting-type="bool"><label data-i18n="settingsHyperlinkAuditingDisabledPrompt" for="hyperlink-auditing-disabled"></label> <a class="fa info" href="http://www.wilderssecurity.com/threads/hyperlink-auditing-aka-a-ping-and-beacon-aka-navigator-sendbeacon.364904/" target="_blank"></a>
|
||||||
<li><input id="webrtc-ipaddress-hidden" type="checkbox" data-setting-name="webrtcIPAddressHidden" data-setting-type="bool"><label data-i18n="settingsWebRTCIPAddressHiddenPrompt" for="webrtc-ipaddress-hidden"></label> <a class="fa info important" href="https://github.com/gorhill/uBlock/wiki/Prevent-WebRTC-from-leaking-local-IP-address" target="_blank"></a>
|
<li><input id="webrtc-ipaddress-hidden" type="checkbox" data-setting-name="webrtcIPAddressHidden" data-setting-type="bool"><label data-i18n="settingsWebRTCIPAddressHiddenPrompt" for="webrtc-ipaddress-hidden"></label> <a class="fa info important" href="https://github.com/gorhill/uBlock/wiki/Prevent-WebRTC-from-leaking-local-IP-address" target="_blank"></a>
|
||||||
</ul>
|
</ul>
|
||||||
|
<li class="subgroup"><span data-i18n="settingPerSiteSwitchGroup"></span><ul>
|
||||||
|
<li><label class="synopsis"><span data-i18n="settingPerSiteSwitchGroupSynopsis"></span> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches" target="_blank"></a></label>
|
||||||
|
<li><input id="no-cosmetic-filtering" type="checkbox" data-setting-name="noCosmeticFiltering" data-setting-type="bool"><label data-i18n="settingsNoCosmeticFilteringPrompt" for="no-cosmetic-filtering"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-cosmetic-filtering" target="_blank"></a>
|
||||||
|
<li><input id="no-large-media" type="checkbox" data-setting-name="noLargeMedia" data-setting-type="bool"><label data-i18n="settingsNoLargeMediaPrompt" for="no-large-media"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-large-media-elements" target="_blank"></a>
|
||||||
|
<li><input id="no-remote-fonts" type="checkbox" data-setting-name="noRemoteFonts" data-setting-type="bool"><label data-i18n="settingsNoRemoteFontsPrompt" for="no-remote-fonts"></label> <a class="fa info" href="https://github.com/gorhill/uBlock/wiki/Per-site-switches#no-remote-fonts" target="_blank"></a>
|
||||||
|
</ul>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="localData" style="margin: 0 1em;">
|
<div id="localData" style="margin: 0 1em;">
|
||||||
|
|
|
@ -24,7 +24,7 @@ source_locale_dir = pj(build_dir, '_locales')
|
||||||
target_locale_dir = pj(build_dir, 'locale')
|
target_locale_dir = pj(build_dir, 'locale')
|
||||||
language_codes = []
|
language_codes = []
|
||||||
descriptions = OrderedDict({})
|
descriptions = OrderedDict({})
|
||||||
title_case_strings = ['pickerContextMenuEntry']
|
title_case_strings = ['pickerContextMenuEntry', 'contextMenuTemporarilyAllowLargeMediaElements']
|
||||||
|
|
||||||
for alpha2 in sorted(os.listdir(source_locale_dir)):
|
for alpha2 in sorted(os.listdir(source_locale_dir)):
|
||||||
locale_path = pj(source_locale_dir, alpha2, 'messages.json')
|
locale_path = pj(source_locale_dir, alpha2, 'messages.json')
|
||||||
|
|
Loading…
Reference in a new issue