mirror of https://github.com/gorhill/uBlock.git
This commit is contained in:
parent
04d17a3d84
commit
3730d7d128
|
@ -83,6 +83,7 @@ html#ublock0-epicker,
|
|||
padding: 2px !important;
|
||||
resize: none !important;
|
||||
width: 100% !important;
|
||||
word-break: break-all !important;
|
||||
}
|
||||
#ublock0-epicker #resultsetCount {
|
||||
background-color: #aaa !important;
|
||||
|
|
|
@ -272,104 +272,118 @@ var highlightElements = function(elems, force) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// TODO: Investigate why diff'ing these two strings returns an incorrect result:
|
||||
// |
|
||||
// /articles/5c1a7aae1854f30006cb26f7/lede/1545239527833-shutterstock_726017572-copy.jpeg?crop=0.8889xw%3A0.9988xh%3B0.1089xw%2C0xh&resize=650%3A*&output-quality=55
|
||||
// /articles/5c1aaea91854f30006cb2f1e/lede/1545253629235-shutterstock_1063990172-copy.jpeg?crop=0.7749xw%3A1xh%3B0.0391xw%2C0xh&resize=650%3A*&output-quality=55
|
||||
// |
|
||||
// This appears to be an issue in the differ, need to investigate it.
|
||||
|
||||
const mergeStrings = function(urls) {
|
||||
if ( urls.length === 0 ) { return ''; }
|
||||
if (
|
||||
urls.length === 1 ||
|
||||
self.diff_match_patch instanceof Function === false
|
||||
) {
|
||||
return urls[0];
|
||||
}
|
||||
const differ = new self.diff_match_patch();
|
||||
let merged = urls[0];
|
||||
for ( let i = 1; i < urls.length; i++ ) {
|
||||
// The differ works at line granularity: we insert a linefeed after
|
||||
// each character to trick the differ to work at character granularity.
|
||||
const diffs = differ.diff_main(
|
||||
//urls[i].replace(/.(?=.)/g, '$&\n'),
|
||||
//merged.replace(/.(?=.)/g, '$&\n')
|
||||
urls[i].split('').join('\n'),
|
||||
merged.split('').join('\n')
|
||||
);
|
||||
const result = [];
|
||||
for ( const diff of diffs ) {
|
||||
if ( diff[0] !== 0 ) {
|
||||
result.push('*');
|
||||
} else {
|
||||
result.push(diff[1].charAt(0));
|
||||
}
|
||||
}
|
||||
// Keep usage of wildcards to a sane level, too many of them can cause
|
||||
// high overhead filters
|
||||
merged =
|
||||
result.join('')
|
||||
.replace(/\*+$/, '')
|
||||
.replace(/\*{2,}/g, '*')
|
||||
.replace(/([^*]{1,2}\*)(?:[^*]{1,2}\*)+/g, '$1');
|
||||
}
|
||||
return merged;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1897
|
||||
// Ignore `data:` URI, they can't be handled by an HTTP observer.
|
||||
|
||||
var backgroundImageURLFromElement = function(elem) {
|
||||
var style = window.getComputedStyle(elem),
|
||||
bgImg = style.backgroundImage || '',
|
||||
matches = /^url\((["']?)([^"']+)\1\)$/.exec(bgImg),
|
||||
url = matches !== null && matches.length === 3 ? matches[2] : '';
|
||||
const backgroundImageURLFromElement = function(elem) {
|
||||
const style = window.getComputedStyle(elem);
|
||||
const bgImg = style.backgroundImage || '';
|
||||
const matches = /^url\((["']?)([^"']+)\1\)$/.exec(bgImg);
|
||||
const url = matches !== null && matches.length === 3 ? matches[2] : '';
|
||||
return url.lastIndexOf('data:', 0) === -1 ? url.slice(0, 1024) : '';
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// https://github.com/gorhill/uBlock/issues/1725#issuecomment-226479197
|
||||
// Limit returned string to 1024 characters.
|
||||
// Also, return only URLs which will be seen by an HTTP observer.
|
||||
// Limit returned string to 1024 characters.
|
||||
// Also, return only URLs which will be seen by an HTTP observer.
|
||||
|
||||
var resourceURLFromElement = function(elem) {
|
||||
var tagName = elem.localName, s;
|
||||
if (
|
||||
(s = netFilter1stSources[tagName]) ||
|
||||
(s = netFilter2ndSources[tagName])
|
||||
) {
|
||||
s = elem[s];
|
||||
if ( typeof s === 'string' && /^https?:\/\//.test(s) ) {
|
||||
return s.slice(0, 1024);
|
||||
const resourceURLFromElement = function(elem) {
|
||||
const tagName = elem.localName;
|
||||
const prop = netFilter1stSources[tagName];
|
||||
if ( prop ) {
|
||||
let src = '';
|
||||
{
|
||||
let s = elem[prop];
|
||||
if ( typeof s === 'string' && /^https?:\/\//.test(s) ) {
|
||||
src = s.slice(0, 1024);
|
||||
}
|
||||
}
|
||||
if ( typeof elem.srcset === 'string' && elem.srcset !== '' ) {
|
||||
const ss = [];
|
||||
for ( let s of elem.srcset.split(/\s*,\s+/) ) {
|
||||
const pos = s.indexOf(' ');
|
||||
if ( pos !== -1 ) { s = s.slice(0, pos); }
|
||||
const parsedURL = new URL(s, document.baseURI);
|
||||
if ( parsedURL.pathname.length > 1 ) {
|
||||
ss.push(parsedURL.href);
|
||||
}
|
||||
}
|
||||
if ( ss.length !== 0 ) {
|
||||
if ( src !== '' ) {
|
||||
ss.push(src);
|
||||
}
|
||||
src = mergeStrings(ss);
|
||||
}
|
||||
}
|
||||
return src;
|
||||
}
|
||||
return backgroundImageURLFromElement(elem);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var netFilterFromUnion = (function() {
|
||||
var reTokenizer = /[^0-9a-z%*]+|[0-9a-z%]+|\*/gi;
|
||||
var a = document.createElement('a');
|
||||
const netFilterFromUnion = function(toMergeURL, out) {
|
||||
const parsedURL = new URL(toMergeURL, document.baseURI);
|
||||
|
||||
return function(to, out) {
|
||||
a.href= to;
|
||||
to = a.pathname + a.search;
|
||||
var from = lastNetFilterUnion;
|
||||
toMergeURL = parsedURL.pathname + parsedURL.search;
|
||||
|
||||
// Reset reference filter when dealing with unrelated URLs
|
||||
if ( from === '' || a.host === '' || a.host !== lastNetFilterHostname ) {
|
||||
lastNetFilterHostname = a.host;
|
||||
lastNetFilterUnion = to;
|
||||
vAPI.messaging.send(
|
||||
'elementPicker',
|
||||
{
|
||||
what: 'elementPickerEprom',
|
||||
lastNetFilterSession: lastNetFilterSession,
|
||||
lastNetFilterHostname: lastNetFilterHostname,
|
||||
lastNetFilterUnion: lastNetFilterUnion
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Related URLs
|
||||
lastNetFilterHostname = a.host;
|
||||
|
||||
var fromTokens = from.match(reTokenizer);
|
||||
var toTokens = to.match(reTokenizer);
|
||||
var toCount = toTokens.length, toIndex = 0;
|
||||
var fromToken, pos;
|
||||
|
||||
for ( var fromIndex = 0; fromIndex < fromTokens.length; fromIndex += 1 ) {
|
||||
fromToken = fromTokens[fromIndex];
|
||||
if ( fromToken === '*' ) {
|
||||
continue;
|
||||
}
|
||||
pos = toTokens.indexOf(fromToken, toIndex);
|
||||
if ( pos === -1 ) {
|
||||
fromTokens[fromIndex] = '*';
|
||||
continue;
|
||||
}
|
||||
if ( pos !== toIndex ) {
|
||||
fromTokens.splice(fromIndex, 0, '*');
|
||||
fromIndex += 1;
|
||||
}
|
||||
toIndex = pos + 1;
|
||||
if ( toIndex === toCount ) {
|
||||
fromTokens = fromTokens.slice(0, fromIndex + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
from = fromTokens.join('').replace(/\*\*+/g, '*');
|
||||
if ( from !== '/*' && from !== to ) {
|
||||
var filter = '||' + lastNetFilterHostname + from;
|
||||
if ( out.indexOf(filter) === -1 ) {
|
||||
out.push(filter);
|
||||
}
|
||||
} else {
|
||||
from = to;
|
||||
}
|
||||
lastNetFilterUnion = from;
|
||||
|
||||
// Remember across element picker sessions
|
||||
// Reset reference filter when dealing with unrelated URLs
|
||||
if (
|
||||
lastNetFilterUnion === '' ||
|
||||
parsedURL.host === '' ||
|
||||
parsedURL.host !== lastNetFilterHostname
|
||||
) {
|
||||
lastNetFilterHostname = parsedURL.host;
|
||||
lastNetFilterUnion = toMergeURL;
|
||||
vAPI.messaging.send(
|
||||
'elementPicker',
|
||||
{
|
||||
|
@ -379,14 +393,40 @@ var netFilterFromUnion = (function() {
|
|||
lastNetFilterUnion: lastNetFilterUnion
|
||||
}
|
||||
);
|
||||
};
|
||||
})();
|
||||
return;
|
||||
}
|
||||
|
||||
// Related URLs
|
||||
lastNetFilterHostname = parsedURL.host;
|
||||
|
||||
let mergedURL = mergeStrings([ toMergeURL, lastNetFilterUnion ]);
|
||||
if ( mergedURL !== '/*' && mergedURL !== toMergeURL ) {
|
||||
const filter = '||' + lastNetFilterHostname + mergedURL;
|
||||
if ( out.indexOf(filter) === -1 ) {
|
||||
out.push(filter);
|
||||
}
|
||||
} else {
|
||||
mergedURL = toMergeURL;
|
||||
}
|
||||
lastNetFilterUnion = mergedURL;
|
||||
|
||||
// Remember across element picker sessions
|
||||
vAPI.messaging.send(
|
||||
'elementPicker',
|
||||
{
|
||||
what: 'elementPickerEprom',
|
||||
lastNetFilterSession: lastNetFilterSession,
|
||||
lastNetFilterHostname: lastNetFilterHostname,
|
||||
lastNetFilterUnion: lastNetFilterUnion
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Extract the best possible net filter, i.e. as specific as possible.
|
||||
|
||||
var netFilterFromElement = function(elem) {
|
||||
const netFilterFromElement = function(elem) {
|
||||
if ( elem === null ) { return 0; }
|
||||
if ( elem.nodeType !== 1 ) { return 0; }
|
||||
let src = resourceURLFromElement(elem);
|
||||
|
@ -429,7 +469,7 @@ var netFilterFromElement = function(elem) {
|
|||
return candidates.length - len;
|
||||
};
|
||||
|
||||
var netFilter1stSources = {
|
||||
const netFilter1stSources = {
|
||||
'audio': 'src',
|
||||
'embed': 'src',
|
||||
'iframe': 'src',
|
||||
|
@ -438,11 +478,11 @@ var netFilter1stSources = {
|
|||
'video': 'src'
|
||||
};
|
||||
|
||||
var netFilter2ndSources = {
|
||||
const netFilter2ndSources = {
|
||||
'img': 'srcset'
|
||||
};
|
||||
|
||||
var filterTypes = {
|
||||
const filterTypes = {
|
||||
'audio': 'media',
|
||||
'embed': 'object',
|
||||
'iframe': 'subdocument',
|
||||
|
@ -1498,7 +1538,7 @@ var stopPicker = function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var startPicker = function(details) {
|
||||
const startPicker = function(details) {
|
||||
pickerRoot.addEventListener('load', stopPicker);
|
||||
|
||||
const frameDoc = pickerRoot.contentDocument;
|
||||
|
@ -1611,7 +1651,7 @@ var startPicker = function(details) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var bootstrapPicker = function() {
|
||||
const bootstrapPicker = function() {
|
||||
pickerRoot.removeEventListener('load', bootstrapPicker);
|
||||
vAPI.shutdown.add(stopPicker);
|
||||
vAPI.messaging.send(
|
||||
|
@ -1626,7 +1666,7 @@ var bootstrapPicker = function() {
|
|||
pickerRoot = document.createElement('iframe');
|
||||
pickerRoot.id = vAPI.sessionId;
|
||||
|
||||
var pickerCSSStyle = [
|
||||
const pickerCSSStyle = [
|
||||
'background: transparent',
|
||||
'border: 0',
|
||||
'border-radius: 0',
|
||||
|
@ -1649,12 +1689,12 @@ var pickerCSSStyle = [
|
|||
].join(' !important;');
|
||||
pickerRoot.style.cssText = pickerCSSStyle;
|
||||
|
||||
var pickerCSS1 = [
|
||||
const pickerCSS1 = [
|
||||
'#' + pickerRoot.id + ' {',
|
||||
pickerCSSStyle,
|
||||
'}'
|
||||
].join('\n');
|
||||
var pickerCSS2 = [
|
||||
const pickerCSS2 = [
|
||||
'[' + pickerRoot.id + '-clickblind] {',
|
||||
'pointer-events: none !important;',
|
||||
'}'
|
||||
|
|
|
@ -407,6 +407,16 @@ var matchBucket = function(url, hostname, bucket, start) {
|
|||
this.epickerTarget = targetElement || '';
|
||||
this.epickerZap = zap || false;
|
||||
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/40
|
||||
// The element picker needs this library
|
||||
vAPI.tabs.injectScript(
|
||||
tabId,
|
||||
{
|
||||
file: '/lib/diff/swatinem_diff.js',
|
||||
runAt: 'document_end'
|
||||
}
|
||||
);
|
||||
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/168
|
||||
// Force activate the target tab once the element picker has been
|
||||
// injected.
|
||||
|
|
Loading…
Reference in New Issue