mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-09 12:22:33 +01:00
Improve interactivity for blocked large media elements
Related issues: - https://github.com/gorhill/uBlock/issues/1390 - https://github.com/gorhill/uBlock/issues/2334 The deadline to interactively load a specific media element has been extended from 2sec to 5sec. Clicking over a blocked large media element will cause uBO to lookup and handle all potentially blocked large elements at the cursor position. This should take care of being able to unblock media elements hidden under other DOM object. The CSS style applied to blocked large media elements has been fine tuned to improve interactivity. uBO will now remember the specific media elements which were unblocked and keep them exempted from being further blocked. This would be an issue when unblocking a video and then a bit later seeking to another point in the video, in which case uBO would again block network requests for that video.
This commit is contained in:
parent
9947fcf4d5
commit
53dd339d78
@ -1641,7 +1641,7 @@ const onMessage = function(request, sender, callback) {
|
|||||||
|
|
||||||
case 'temporarilyAllowLargeMediaElement':
|
case 'temporarilyAllowLargeMediaElement':
|
||||||
if ( pageStore !== null ) {
|
if ( pageStore !== null ) {
|
||||||
pageStore.allowLargeMediaElementsUntil = Date.now() + 2000;
|
pageStore.allowLargeMediaElementsUntil = Date.now() + 5000;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ const PageStore = class {
|
|||||||
typeof this.allowLargeMediaElementsUntil !== 'number' ||
|
typeof this.allowLargeMediaElementsUntil !== 'number' ||
|
||||||
tabContext.rootHostname !== this.tabHostname
|
tabContext.rootHostname !== this.tabHostname
|
||||||
) {
|
) {
|
||||||
this.allowLargeMediaElementsUntil = 0;
|
this.allowLargeMediaElementsUntil = Date.now();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tabHostname = tabContext.rootHostname;
|
this.tabHostname = tabContext.rootHostname;
|
||||||
@ -260,6 +260,7 @@ const PageStore = class {
|
|||||||
this.largeMediaCount = 0;
|
this.largeMediaCount = 0;
|
||||||
this.largeMediaTimer = null;
|
this.largeMediaTimer = null;
|
||||||
this.internalRedirectionCount = 0;
|
this.internalRedirectionCount = 0;
|
||||||
|
this.allowLargeMediaElementsRegex = undefined;
|
||||||
this.extraData.clear();
|
this.extraData.clear();
|
||||||
|
|
||||||
this.frameAddCount = 0;
|
this.frameAddCount = 0;
|
||||||
@ -339,7 +340,8 @@ const PageStore = class {
|
|||||||
this.rawURL = '';
|
this.rawURL = '';
|
||||||
this.hostnameToCountMap = null;
|
this.hostnameToCountMap = null;
|
||||||
this.netFilteringCache.empty();
|
this.netFilteringCache.empty();
|
||||||
this.allowLargeMediaElementsUntil = 0;
|
this.allowLargeMediaElementsUntil = Date.now();
|
||||||
|
this.allowLargeMediaElementsRegex = undefined;
|
||||||
if ( this.largeMediaTimer !== null ) {
|
if ( this.largeMediaTimer !== null ) {
|
||||||
clearTimeout(this.largeMediaTimer);
|
clearTimeout(this.largeMediaTimer);
|
||||||
this.largeMediaTimer = null;
|
this.largeMediaTimer = null;
|
||||||
@ -438,7 +440,12 @@ const PageStore = class {
|
|||||||
temporarilyAllowLargeMediaElements(state) {
|
temporarilyAllowLargeMediaElements(state) {
|
||||||
this.largeMediaCount = 0;
|
this.largeMediaCount = 0;
|
||||||
µb.contextMenu.update(this.tabId);
|
µb.contextMenu.update(this.tabId);
|
||||||
this.allowLargeMediaElementsUntil = state ? Date.now() + 86400000 : 0;
|
if ( state ) {
|
||||||
|
this.allowLargeMediaElementsUntil = 0;
|
||||||
|
this.allowLargeMediaElementsRegex = undefined;
|
||||||
|
} else {
|
||||||
|
this.allowLargeMediaElementsUntil = Date.now();
|
||||||
|
}
|
||||||
µb.scriptlets.injectDeep(this.tabId, 'load-large-media-all');
|
µb.scriptlets.injectDeep(this.tabId, 'load-large-media-all');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,7 +711,23 @@ const PageStore = class {
|
|||||||
filterLargeMediaElement(fctxt, size) {
|
filterLargeMediaElement(fctxt, size) {
|
||||||
fctxt.filter = undefined;
|
fctxt.filter = undefined;
|
||||||
|
|
||||||
|
if ( this.allowLargeMediaElementsUntil === 0 ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// Disregard large media elements previously allowed: for example, to
|
||||||
|
// seek inside a previously allowed audio/video.
|
||||||
|
if (
|
||||||
|
this.allowLargeMediaElementsRegex instanceof RegExp &&
|
||||||
|
this.allowLargeMediaElementsRegex.test(fctxt.url)
|
||||||
|
) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if ( Date.now() < this.allowLargeMediaElementsUntil ) {
|
if ( Date.now() < this.allowLargeMediaElementsUntil ) {
|
||||||
|
const sources = this.allowLargeMediaElementsRegex instanceof RegExp
|
||||||
|
? [ this.allowLargeMediaElementsRegex.source ]
|
||||||
|
: [];
|
||||||
|
sources.push('^' + µb.escapeRegex(fctxt.url));
|
||||||
|
this.allowLargeMediaElementsRegex = new RegExp(sources.join('|'));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@ -713,6 +736,7 @@ const PageStore = class {
|
|||||||
fctxt.getTabHostname()
|
fctxt.getTabHostname()
|
||||||
) !== true
|
) !== true
|
||||||
) {
|
) {
|
||||||
|
this.allowLargeMediaElementsUntil = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
|
if ( (size >>> 10) < µb.userSettings.largeMediaSize ) {
|
||||||
|
@ -19,48 +19,36 @@
|
|||||||
Home: https://github.com/gorhill/uBlock
|
Home: https://github.com/gorhill/uBlock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
(function() {
|
(( ) => {
|
||||||
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
// For all media resources which have failed to load, trigger a reload.
|
// For all media resources which have failed to load, trigger a reload.
|
||||||
|
|
||||||
var elems, i, elem, src;
|
|
||||||
|
|
||||||
// <audio> and <video> elements.
|
// <audio> and <video> elements.
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
|
||||||
elems = document.querySelectorAll('audio,video');
|
for ( const elem of document.querySelectorAll('audio,video') ) {
|
||||||
i = elems.length;
|
if ( elem.error === null ) { continue; }
|
||||||
while ( i-- ) {
|
elem.load();
|
||||||
elem = elems[i];
|
|
||||||
if ( elem.error !== null ) {
|
|
||||||
elem.load();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// <img> elements.
|
// <img> elements.
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
|
||||||
elems = document.querySelectorAll('img');
|
for ( const elem of document.querySelectorAll('img') ) {
|
||||||
i = elems.length;
|
if ( elem.naturalWidth !== 0 && elem.naturalHeight !== 0 ) { continue; }
|
||||||
while ( i-- ) {
|
|
||||||
elem = elems[i];
|
|
||||||
if ( elem.naturalWidth !== 0 && elem.naturalHeight !== 0 ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ( window.getComputedStyle(elem).getPropertyValue('display') === 'none' ) {
|
if ( window.getComputedStyle(elem).getPropertyValue('display') === 'none' ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
src = elem.getAttribute('src');
|
const src = elem.getAttribute('src') || '';
|
||||||
if ( src ) {
|
if ( src === '' ) { continue; }
|
||||||
elem.removeAttribute('src');
|
elem.removeAttribute('src');
|
||||||
elem.setAttribute('src', src);
|
elem.setAttribute('src', src);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -36,9 +36,10 @@ if ( typeof vAPI !== 'object' || vAPI.loadLargeMediaInteractive === true ) {
|
|||||||
|
|
||||||
const largeMediaElementAttribute = 'data-' + vAPI.sessionId;
|
const largeMediaElementAttribute = 'data-' + vAPI.sessionId;
|
||||||
const largeMediaElementSelector =
|
const largeMediaElementSelector =
|
||||||
':root audio[' + largeMediaElementAttribute + '],\n' +
|
':root audio[' + largeMediaElementAttribute + '],\n' +
|
||||||
':root img[' + largeMediaElementAttribute + '],\n' +
|
':root img[' + largeMediaElementAttribute + '],\n' +
|
||||||
':root video[' + largeMediaElementAttribute + ']';
|
':root picture[' + largeMediaElementAttribute + '],\n' +
|
||||||
|
':root video[' + largeMediaElementAttribute + ']';
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
@ -51,9 +52,7 @@ const mediaNotLoaded = function(elem) {
|
|||||||
case 'video':
|
case 'video':
|
||||||
return elem.error !== null;
|
return elem.error !== null;
|
||||||
case 'img':
|
case 'img':
|
||||||
if ( elem.naturalWidth !== 0 || elem.naturalHeight !== 0 ) {
|
if ( elem.naturalWidth !== 0 || elem.naturalHeight !== 0 ) { break; }
|
||||||
break;
|
|
||||||
}
|
|
||||||
const style = window.getComputedStyle(elem);
|
const style = window.getComputedStyle(elem);
|
||||||
// For some reason, style can be null with Pale Moon.
|
// For some reason, style can be null with Pale Moon.
|
||||||
return style !== null ?
|
return style !== null ?
|
||||||
@ -74,50 +73,57 @@ const mediaNotLoaded = function(elem) {
|
|||||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
|
||||||
|
|
||||||
const surveyMissingMediaElements = function() {
|
const surveyMissingMediaElements = function() {
|
||||||
var largeMediaElementCount = 0;
|
let largeMediaElementCount = 0;
|
||||||
var elems = document.querySelectorAll('audio,img,video');
|
for ( const elem of document.querySelectorAll('audio,img,video') ) {
|
||||||
var i = elems.length, elem;
|
if ( mediaNotLoaded(elem) === false ) { continue; }
|
||||||
while ( i-- ) {
|
elem.setAttribute(largeMediaElementAttribute, '');
|
||||||
elem = elems[i];
|
largeMediaElementCount += 1;
|
||||||
if ( mediaNotLoaded(elem) ) {
|
switch ( elem.localName ) {
|
||||||
elem.setAttribute(largeMediaElementAttribute, '');
|
case 'img': {
|
||||||
largeMediaElementCount += 1;
|
const picture = elem.closest('picture');
|
||||||
|
if ( picture !== null ) {
|
||||||
|
picture.setAttribute(largeMediaElementAttribute, '');
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return largeMediaElementCount;
|
return largeMediaElementCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
if ( surveyMissingMediaElements() === 0 ) {
|
if ( surveyMissingMediaElements() === 0 ) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
vAPI.loadLargeMediaInteractive = true;
|
vAPI.loadLargeMediaInteractive = true;
|
||||||
|
|
||||||
// Insert custom style tag.
|
// Insert CSS to highlight blocked media elements.
|
||||||
let styleTag = document.createElement('style');
|
if ( vAPI.largeMediaElementStyleSheet === undefined ) {
|
||||||
styleTag.setAttribute('type', 'text/css');
|
vAPI.largeMediaElementStyleSheet = [
|
||||||
styleTag.textContent = [
|
largeMediaElementSelector + ' {',
|
||||||
largeMediaElementSelector + ' {',
|
'border: 2px dotted red !important;',
|
||||||
'border: 1px dotted red !important;',
|
'box-sizing: border-box !important;',
|
||||||
'box-sizing: border-box !important;',
|
'cursor: zoom-in !important;',
|
||||||
'cursor: zoom-in !important;',
|
'display: inline-block;',
|
||||||
'display: inline-block;',
|
'font-size: 1rem !important;',
|
||||||
'font-size: 1em !important;',
|
'min-height: 1em !important;',
|
||||||
'min-height: 1em !important;',
|
'min-width: 1em !important;',
|
||||||
'min-width: 1em !important;',
|
'opacity: 1 !important;',
|
||||||
'opacity: 1 !important;',
|
'outline: none !important;',
|
||||||
'outline: none !important;',
|
'visibility: visible !important;',
|
||||||
'}'
|
'z-index: 2147483647',
|
||||||
].join('\n');
|
'}',
|
||||||
document.head.appendChild(styleTag);
|
].join('\n');
|
||||||
|
vAPI.userStylesheet.add(vAPI.largeMediaElementStyleSheet);
|
||||||
|
vAPI.userStylesheet.apply();
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const stayOrLeave = (( ) => {
|
const stayOrLeave = (( ) => {
|
||||||
let timer = null;
|
let timer;
|
||||||
|
|
||||||
const timeoutHandler = function(leaveNow) {
|
const timeoutHandler = function(leaveNow) {
|
||||||
timer = null;
|
timer = undefined;
|
||||||
if ( leaveNow !== true ) {
|
if ( leaveNow !== true ) {
|
||||||
if (
|
if (
|
||||||
document.querySelector(largeMediaElementSelector) !== null ||
|
document.querySelector(largeMediaElementSelector) !== null ||
|
||||||
@ -127,9 +133,8 @@ const stayOrLeave = (( ) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Leave
|
// Leave
|
||||||
if ( styleTag !== null ) {
|
for ( const elem of document.querySelectorAll(largeMediaElementSelector) ) {
|
||||||
styleTag.parentNode.removeChild(styleTag);
|
elem.removeAttribute(largeMediaElementAttribute);
|
||||||
styleTag = null;
|
|
||||||
}
|
}
|
||||||
vAPI.loadLargeMediaInteractive = false;
|
vAPI.loadLargeMediaInteractive = false;
|
||||||
document.removeEventListener('error', onLoadError, true);
|
document.removeEventListener('error', onLoadError, true);
|
||||||
@ -137,7 +142,7 @@ const stayOrLeave = (( ) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return function(leaveNow) {
|
return function(leaveNow) {
|
||||||
if ( timer !== null ) {
|
if ( timer !== undefined ) {
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
}
|
}
|
||||||
if ( leaveNow ) {
|
if ( leaveNow ) {
|
||||||
@ -160,24 +165,44 @@ const loadImage = async function(elem) {
|
|||||||
|
|
||||||
elem.setAttribute('src', src);
|
elem.setAttribute('src', src);
|
||||||
elem.removeAttribute(largeMediaElementAttribute);
|
elem.removeAttribute(largeMediaElementAttribute);
|
||||||
|
|
||||||
|
switch ( elem.localName ) {
|
||||||
|
case 'img': {
|
||||||
|
const picture = elem.closest('picture');
|
||||||
|
if ( picture !== null ) {
|
||||||
|
picture.removeAttribute(largeMediaElementAttribute);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
stayOrLeave();
|
stayOrLeave();
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const onMouseClick = function(ev) {
|
const onMouseClick = function(ev) {
|
||||||
if ( ev.button !== 0 ) { return; }
|
if ( ev.button !== 0 || ev.isTrusted === false ) { return; }
|
||||||
|
|
||||||
const elem = ev.target;
|
const toLoad = [];
|
||||||
if ( elem.matches(largeMediaElementSelector) === false ) { return; }
|
const elems = document.elementsFromPoint instanceof Function
|
||||||
|
? document.elementsFromPoint(ev.clientX, ev.clientY)
|
||||||
|
: [ ev.target ];
|
||||||
|
for ( const elem of elems ) {
|
||||||
|
if ( elem.matches(largeMediaElementSelector) && mediaNotLoaded(elem) ) {
|
||||||
|
toLoad.push(elem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( mediaNotLoaded(elem) === false ) {
|
if ( toLoad.length === 0 ) {
|
||||||
elem.removeAttribute(largeMediaElementAttribute);
|
|
||||||
stayOrLeave();
|
stayOrLeave();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadImage(elem);
|
for ( const elem of toLoad ) {
|
||||||
|
loadImage(elem);
|
||||||
|
}
|
||||||
|
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
@ -210,7 +235,7 @@ document.addEventListener('error', onLoadError, true);
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
vAPI.shutdown.add(function() {
|
vAPI.shutdown.add(( ) => {
|
||||||
stayOrLeave(true);
|
stayOrLeave(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -469,7 +469,7 @@ const onHeadersReceived = function(details) {
|
|||||||
if ( isRootDoc ) {
|
if ( isRootDoc ) {
|
||||||
const contentType = headerValueFromName('content-type', responseHeaders);
|
const contentType = headerValueFromName('content-type', responseHeaders);
|
||||||
if ( reMediaContentTypes.test(contentType) ) {
|
if ( reMediaContentTypes.test(contentType) ) {
|
||||||
pageStore.allowLargeMediaElementsUntil = Date.now() + 86400000;
|
pageStore.allowLargeMediaElementsUntil = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user