mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-13 02:14:17 +01:00
Fix having picker & inspector active at the same time
Related feedback: https://github.com/uBlockOrigin/uBlock-issues/issues/3004#issuecomment-1863610146
This commit is contained in:
parent
698bec4f5b
commit
9a8dd66517
2 changed files with 91 additions and 87 deletions
|
@ -31,28 +31,26 @@
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
if ( typeof vAPI !== 'object' ) { return; }
|
if ( typeof vAPI !== 'object' ) { return; }
|
||||||
|
if ( typeof vAPI === null ) { return; }
|
||||||
if ( vAPI.domFilterer instanceof Object === false ) { return; }
|
if ( vAPI.domFilterer instanceof Object === false ) { return; }
|
||||||
if ( document.querySelector(`iframe[${vAPI.sessionId}]`) !== null ) { return; }
|
|
||||||
|
|
||||||
/******************************************************************************/
|
if ( vAPI.inspectorFrame ) { return; }
|
||||||
/******************************************************************************/
|
vAPI.inspectorFrame = true;
|
||||||
|
|
||||||
|
const inspectorUniqueId = vAPI.randomToken();
|
||||||
|
|
||||||
const nodeToIdMap = new WeakMap(); // No need to iterate
|
const nodeToIdMap = new WeakMap(); // No need to iterate
|
||||||
|
|
||||||
let blueNodes = [];
|
let blueNodes = [];
|
||||||
const roRedNodes = new Map(); // node => current cosmetic filter
|
const roRedNodes = new Map(); // node => current cosmetic filter
|
||||||
const rwRedNodes = new Set(); // node => new cosmetic filter (toggle node)
|
const rwRedNodes = new Set(); // node => new cosmetic filter (toggle node)
|
||||||
//var roGreenNodes = new Map(); // node => current exception cosmetic filter (can't toggle)
|
|
||||||
const rwGreenNodes = new Set(); // node => new exception cosmetic filter (toggle filter)
|
const rwGreenNodes = new Set(); // node => new exception cosmetic filter (toggle filter)
|
||||||
|
//const roGreenNodes = new Map(); // node => current exception cosmetic filter (can't toggle)
|
||||||
|
|
||||||
const reHasCSSCombinators = /[ >+~]/;
|
const reHasCSSCombinators = /[ >+~]/;
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
//const getNodeId = node => nodeToIdMap.get(node) || 0;
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
const domLayout = (( ) => {
|
const domLayout = (( ) => {
|
||||||
const skipTagNames = new Set([
|
const skipTagNames = new Set([
|
||||||
'br', 'head', 'link', 'meta', 'script', 'style', 'title'
|
'br', 'head', 'link', 'meta', 'script', 'style', 'title'
|
||||||
|
@ -670,11 +668,13 @@ const shutdownInspector = ( ) => {
|
||||||
passive: true,
|
passive: true,
|
||||||
});
|
});
|
||||||
contentInspectorChannel.shutdown();
|
contentInspectorChannel.shutdown();
|
||||||
vAPI.userStylesheet.remove(inspectorCSS);
|
if ( inspectorFrame ) {
|
||||||
vAPI.userStylesheet.apply();
|
|
||||||
if ( inspectorFrame === null ) { return; }
|
|
||||||
inspectorFrame.remove();
|
inspectorFrame.remove();
|
||||||
inspectorFrame = null;
|
inspectorFrame = null;
|
||||||
|
}
|
||||||
|
vAPI.userStylesheet.remove(inspectorCSS);
|
||||||
|
vAPI.userStylesheet.apply();
|
||||||
|
vAPI.inspectorFrame = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -826,22 +826,22 @@ const contentInspectorChannel = (( ) => {
|
||||||
if ( inspectorArgs === null ) { return; }
|
if ( inspectorArgs === null ) { return; }
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const iframe = document.createElement('iframe');
|
const iframe = document.createElement('iframe');
|
||||||
iframe.setAttribute(vAPI.sessionId, '');
|
iframe.setAttribute(inspectorUniqueId, '');
|
||||||
document.documentElement.append(iframe);
|
document.documentElement.append(iframe);
|
||||||
iframe.addEventListener('load', ( ) => {
|
iframe.addEventListener('load', ( ) => {
|
||||||
iframe.setAttribute(`${vAPI.sessionId}-loaded`, '');
|
iframe.setAttribute(`${inspectorUniqueId}-loaded`, '');
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
toFramePort = channel.port1;
|
toFramePort = channel.port1;
|
||||||
toFramePort.onmessage = ev => {
|
toFramePort.onmessage = ev => {
|
||||||
const msg = ev.data || {};
|
const msg = ev.data || {};
|
||||||
if ( msg.what !== 'startInspector' ) { return; }
|
if ( msg.what !== 'startInspector' ) { return; }
|
||||||
resolve(iframe);
|
|
||||||
};
|
};
|
||||||
iframe.contentWindow.postMessage(
|
iframe.contentWindow.postMessage(
|
||||||
{ what: 'startInspector' },
|
{ what: 'startInspector' },
|
||||||
inspectorArgs.inspectorURL,
|
inspectorArgs.inspectorURL,
|
||||||
[ channel.port2 ]
|
[ channel.port2 ]
|
||||||
);
|
);
|
||||||
|
resolve(iframe);
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
iframe.contentWindow.location = inspectorArgs.inspectorURL;
|
iframe.contentWindow.location = inspectorArgs.inspectorURL;
|
||||||
});
|
});
|
||||||
|
@ -859,26 +859,32 @@ const inspectorCSSStyle = [
|
||||||
'box-shadow: none',
|
'box-shadow: none',
|
||||||
'color-scheme: light dark',
|
'color-scheme: light dark',
|
||||||
'display: block',
|
'display: block',
|
||||||
|
'filter: none',
|
||||||
'height: 100%',
|
'height: 100%',
|
||||||
'left: 0',
|
'left: 0',
|
||||||
'margin: 0',
|
'margin: 0',
|
||||||
|
'max-height: none',
|
||||||
|
'max-width: none',
|
||||||
|
'min-height: unset',
|
||||||
|
'min-width: unset',
|
||||||
'opacity: 1',
|
'opacity: 1',
|
||||||
'outline: 0',
|
'outline: 0',
|
||||||
'padding: 0',
|
'padding: 0',
|
||||||
'pointer-events: none',
|
'pointer-events: none',
|
||||||
'position: fixed',
|
'position: fixed',
|
||||||
'top: 0',
|
'top: 0',
|
||||||
'visibility: visible',
|
'transform: none',
|
||||||
|
'visibility: hidden',
|
||||||
'width: 100%',
|
'width: 100%',
|
||||||
'z-index: 2147483647',
|
'z-index: 2147483647',
|
||||||
''
|
''
|
||||||
].join(' !important;\n');
|
].join(' !important;\n');
|
||||||
|
|
||||||
const inspectorCSS = `
|
const inspectorCSS = `
|
||||||
:root > [${vAPI.sessionId}] {
|
:root > [${inspectorUniqueId}] {
|
||||||
${inspectorCSSStyle}
|
${inspectorCSSStyle}
|
||||||
}
|
}
|
||||||
:root > [${vAPI.sessionId}-loaded] {
|
:root > [${inspectorUniqueId}-loaded] {
|
||||||
visibility: visible !important;
|
visibility: visible !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -30,18 +30,13 @@
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
if ( typeof vAPI !== 'object' || vAPI === null ) {
|
if ( typeof vAPI !== 'object' ) { return; }
|
||||||
return;
|
if ( typeof vAPI === null ) { return; }
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
if ( vAPI.pickerFrame ) { return; }
|
||||||
|
vAPI.pickerFrame = true;
|
||||||
|
|
||||||
const epickerId = vAPI.randomToken();
|
const pickerUniqueId = vAPI.randomToken();
|
||||||
|
|
||||||
let pickerRoot = document.querySelector(`[${vAPI.sessionId}]`);
|
|
||||||
if ( pickerRoot !== null ) { return; }
|
|
||||||
|
|
||||||
let pickerBootArgs;
|
|
||||||
|
|
||||||
const reCosmeticAnchor = /^#(\$|\?|\$\?)?#/;
|
const reCosmeticAnchor = /^#(\$|\?|\$\?)?#/;
|
||||||
|
|
||||||
|
@ -128,7 +123,7 @@ const highlightElements = function(elems, force) {
|
||||||
const islands = [];
|
const islands = [];
|
||||||
|
|
||||||
for ( const elem of elems ) {
|
for ( const elem of elems ) {
|
||||||
if ( elem === pickerRoot ) { continue; }
|
if ( elem === pickerFrame ) { continue; }
|
||||||
targetElements.push(elem);
|
targetElements.push(elem);
|
||||||
const rect = getElementBoundingClientRect(elem);
|
const rect = getElementBoundingClientRect(elem);
|
||||||
// Ignore offscreen areas
|
// Ignore offscreen areas
|
||||||
|
@ -554,10 +549,10 @@ const filtersFrom = function(x, y) {
|
||||||
// https://www.reddit.com/r/uBlockOrigin/comments/qmjk36/
|
// https://www.reddit.com/r/uBlockOrigin/comments/qmjk36/
|
||||||
// Extract network candidates first.
|
// Extract network candidates first.
|
||||||
if ( typeof x === 'number' ) {
|
if ( typeof x === 'number' ) {
|
||||||
const magicAttr = `${vAPI.sessionId}-clickblind`;
|
const magicAttr = `${pickerUniqueId}-clickblind`;
|
||||||
pickerRoot.setAttribute(magicAttr, '');
|
pickerFrame.setAttribute(magicAttr, '');
|
||||||
const elems = document.elementsFromPoint(x, y);
|
const elems = document.elementsFromPoint(x, y);
|
||||||
pickerRoot.removeAttribute(magicAttr);
|
pickerFrame.removeAttribute(magicAttr);
|
||||||
for ( const elem of elems ) {
|
for ( const elem of elems ) {
|
||||||
netFilterFromElement(elem);
|
netFilterFromElement(elem);
|
||||||
}
|
}
|
||||||
|
@ -737,7 +732,7 @@ const filterToDOMInterface = (( ) => {
|
||||||
}
|
}
|
||||||
const out = [];
|
const out = [];
|
||||||
for ( const elem of elems ) {
|
for ( const elem of elems ) {
|
||||||
if ( elem === pickerRoot ) { continue; }
|
if ( elem === pickerFrame ) { continue; }
|
||||||
out.push({ elem, raw, style: vAPI.hideStyle });
|
out.push({ elem, raw, style: vAPI.hideStyle });
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
@ -815,7 +810,7 @@ const filterToDOMInterface = (( ) => {
|
||||||
if ( Array.isArray(lastResultset) === false ) { return; }
|
if ( Array.isArray(lastResultset) === false ) { return; }
|
||||||
const rootElem = document.documentElement;
|
const rootElem = document.documentElement;
|
||||||
for ( const { elem, style } of lastResultset ) {
|
for ( const { elem, style } of lastResultset ) {
|
||||||
if ( elem === pickerRoot ) { continue; }
|
if ( elem === pickerFrame ) { continue; }
|
||||||
if ( style === undefined ) { continue; }
|
if ( style === undefined ) { continue; }
|
||||||
if ( elem === rootElem && style === vAPI.hideStyle ) { continue; }
|
if ( elem === rootElem && style === vAPI.hideStyle ) { continue; }
|
||||||
let styleToken = vAPI.epickerStyleProxies.get(style);
|
let styleToken = vAPI.epickerStyleProxies.get(style);
|
||||||
|
@ -932,9 +927,9 @@ const elementFromPoint = (( ) => {
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ( !pickerRoot ) { return null; }
|
if ( !pickerFrame ) { return null; }
|
||||||
const magicAttr = `${vAPI.sessionId}-clickblind`;
|
const magicAttr = `${pickerUniqueId}-clickblind`;
|
||||||
pickerRoot.setAttribute(magicAttr, '');
|
pickerFrame.setAttribute(magicAttr, '');
|
||||||
let elem = document.elementFromPoint(x, y);
|
let elem = document.elementFromPoint(x, y);
|
||||||
if (
|
if (
|
||||||
elem === null || /* to skip following tests */
|
elem === null || /* to skip following tests */
|
||||||
|
@ -948,7 +943,7 @@ const elementFromPoint = (( ) => {
|
||||||
elem = null;
|
elem = null;
|
||||||
}
|
}
|
||||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/380
|
// https://github.com/uBlockOrigin/uBlock-issues/issues/380
|
||||||
pickerRoot.removeAttribute(magicAttr);
|
pickerFrame.removeAttribute(magicAttr);
|
||||||
return elem;
|
return elem;
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
@ -1064,7 +1059,7 @@ const onViewportChanged = function() {
|
||||||
// Auto-select a specific target, if any, and if possible
|
// Auto-select a specific target, if any, and if possible
|
||||||
|
|
||||||
const startPicker = function() {
|
const startPicker = function() {
|
||||||
pickerRoot.focus();
|
pickerFrame.focus();
|
||||||
|
|
||||||
self.addEventListener('scroll', onViewportChanged, { passive: true });
|
self.addEventListener('scroll', onViewportChanged, { passive: true });
|
||||||
self.addEventListener('resize', onViewportChanged, { passive: true });
|
self.addEventListener('resize', onViewportChanged, { passive: true });
|
||||||
|
@ -1101,7 +1096,7 @@ const startPicker = function() {
|
||||||
if ( attr === undefined ) { return; }
|
if ( attr === undefined ) { return; }
|
||||||
const elems = document.getElementsByTagName(tagName);
|
const elems = document.getElementsByTagName(tagName);
|
||||||
for ( const elem of elems ) {
|
for ( const elem of elems ) {
|
||||||
if ( elem === pickerRoot ) { continue; }
|
if ( elem === pickerFrame ) { continue; }
|
||||||
const srcs = resourceURLsFromElement(elem);
|
const srcs = resourceURLsFromElement(elem);
|
||||||
if (
|
if (
|
||||||
(srcs.length !== 0 && srcs.includes(url) === false) ||
|
(srcs.length !== 0 && srcs.includes(url) === false) ||
|
||||||
|
@ -1140,19 +1135,22 @@ const quitPicker = function() {
|
||||||
self.removeEventListener('resize', onViewportChanged, { passive: true });
|
self.removeEventListener('resize', onViewportChanged, { passive: true });
|
||||||
self.removeEventListener('keydown', onKeyPressed, true);
|
self.removeEventListener('keydown', onKeyPressed, true);
|
||||||
vAPI.shutdown.remove(quitPicker);
|
vAPI.shutdown.remove(quitPicker);
|
||||||
if ( pickerFramePort !== null ) {
|
if ( pickerFramePort ) {
|
||||||
pickerFramePort.close();
|
pickerFramePort.close();
|
||||||
pickerFramePort = null;
|
pickerFramePort = null;
|
||||||
}
|
}
|
||||||
if ( pickerRoot !== null ) {
|
if ( pickerFrame ) {
|
||||||
pickerRoot.remove();
|
pickerFrame.remove();
|
||||||
pickerRoot = null;
|
pickerFrame = null;
|
||||||
}
|
}
|
||||||
vAPI.userStylesheet.remove(pickerCSS);
|
vAPI.userStylesheet.remove(pickerCSS);
|
||||||
vAPI.userStylesheet.apply();
|
vAPI.userStylesheet.apply();
|
||||||
|
vAPI.pickerFrame = false;
|
||||||
self.focus();
|
self.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vAPI.shutdown.add(quitPicker);
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const onDialogMessage = function(msg) {
|
const onDialogMessage = function(msg) {
|
||||||
|
@ -1232,21 +1230,6 @@ const onDialogMessage = function(msg) {
|
||||||
// of the iframe, and cannot interfere with its style properties. However the
|
// of the iframe, and cannot interfere with its style properties. However the
|
||||||
// page can remove the iframe.
|
// page can remove the iframe.
|
||||||
|
|
||||||
// fetch/process picker arguments.
|
|
||||||
{
|
|
||||||
pickerBootArgs = await vAPI.messaging.send('elementPicker', {
|
|
||||||
what: 'elementPickerArguments',
|
|
||||||
});
|
|
||||||
if ( typeof pickerBootArgs !== 'object' ) { return; }
|
|
||||||
if ( pickerBootArgs === null ) { return; }
|
|
||||||
// Restore net filter union data if origin is the same.
|
|
||||||
const eprom = pickerBootArgs.eprom || null;
|
|
||||||
if ( eprom !== null && eprom.lastNetFilterSession === lastNetFilterSession ) {
|
|
||||||
lastNetFilterHostname = eprom.lastNetFilterHostname || '';
|
|
||||||
lastNetFilterUnion = eprom.lastNetFilterUnion || '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The DOM filterer will not be present when cosmetic filtering is disabled.
|
// The DOM filterer will not be present when cosmetic filtering is disabled.
|
||||||
const noCosmeticFiltering =
|
const noCosmeticFiltering =
|
||||||
vAPI.domFilterer instanceof Object === false ||
|
vAPI.domFilterer instanceof Object === false ||
|
||||||
|
@ -1285,13 +1268,13 @@ const pickerCSSStyle = [
|
||||||
|
|
||||||
|
|
||||||
const pickerCSS = `
|
const pickerCSS = `
|
||||||
:root > [${vAPI.sessionId}] {
|
:root > [${pickerUniqueId}] {
|
||||||
${pickerCSSStyle}
|
${pickerCSSStyle}
|
||||||
}
|
}
|
||||||
:root > [${vAPI.sessionId}-loaded] {
|
:root > [${pickerUniqueId}-loaded] {
|
||||||
visibility: visible !important;
|
visibility: visible !important;
|
||||||
}
|
}
|
||||||
:root [${vAPI.sessionId}-clickblind] {
|
:root [${pickerUniqueId}-clickblind] {
|
||||||
pointer-events: none !important;
|
pointer-events: none !important;
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
@ -1299,38 +1282,53 @@ const pickerCSS = `
|
||||||
vAPI.userStylesheet.add(pickerCSS);
|
vAPI.userStylesheet.add(pickerCSS);
|
||||||
vAPI.userStylesheet.apply();
|
vAPI.userStylesheet.apply();
|
||||||
|
|
||||||
pickerRoot = document.createElement('iframe');
|
let pickerBootArgs;
|
||||||
pickerRoot.setAttribute(vAPI.sessionId, '');
|
|
||||||
document.documentElement.append(pickerRoot);
|
|
||||||
|
|
||||||
vAPI.shutdown.add(quitPicker);
|
|
||||||
|
|
||||||
let pickerFramePort = null;
|
let pickerFramePort = null;
|
||||||
|
|
||||||
{
|
const bootstrap = async ( ) => {
|
||||||
|
pickerBootArgs = await vAPI.messaging.send('elementPicker', {
|
||||||
|
what: 'elementPickerArguments',
|
||||||
|
});
|
||||||
|
if ( typeof pickerBootArgs !== 'object' ) { return; }
|
||||||
|
if ( pickerBootArgs === null ) { return; }
|
||||||
|
// Restore net filter union data if origin is the same.
|
||||||
|
const eprom = pickerBootArgs.eprom || null;
|
||||||
|
if ( eprom !== null && eprom.lastNetFilterSession === lastNetFilterSession ) {
|
||||||
|
lastNetFilterHostname = eprom.lastNetFilterHostname || '';
|
||||||
|
lastNetFilterUnion = eprom.lastNetFilterUnion || '';
|
||||||
|
}
|
||||||
const url = new URL(pickerBootArgs.pickerURL);
|
const url = new URL(pickerBootArgs.pickerURL);
|
||||||
url.searchParams.set('epid', epickerId);
|
|
||||||
if ( pickerBootArgs.zap ) {
|
if ( pickerBootArgs.zap ) {
|
||||||
url.searchParams.set('zap', '1');
|
url.searchParams.set('zap', '1');
|
||||||
}
|
}
|
||||||
pickerRoot.addEventListener('load', ( ) => {
|
return new Promise(resolve => {
|
||||||
|
const iframe = document.createElement('iframe');
|
||||||
|
iframe.setAttribute(pickerUniqueId, '');
|
||||||
|
document.documentElement.append(iframe);
|
||||||
|
iframe.addEventListener('load', ( ) => {
|
||||||
|
iframe.setAttribute(`${pickerUniqueId}-loaded`, '');
|
||||||
const channel = new MessageChannel();
|
const channel = new MessageChannel();
|
||||||
pickerFramePort = channel.port1;
|
pickerFramePort = channel.port1;
|
||||||
pickerFramePort.onmessage = ev => {
|
pickerFramePort.onmessage = ev => {
|
||||||
const msg = ev.data || {};
|
onDialogMessage(ev.data || {});
|
||||||
onDialogMessage(msg);
|
|
||||||
};
|
};
|
||||||
pickerFramePort.onmessageerror = ( ) => {
|
pickerFramePort.onmessageerror = ( ) => {
|
||||||
quitPicker();
|
quitPicker();
|
||||||
};
|
};
|
||||||
pickerRoot.setAttribute(`${vAPI.sessionId}-loaded`, '');
|
iframe.contentWindow.postMessage(
|
||||||
pickerRoot.contentWindow.postMessage(
|
|
||||||
{ what: 'epickerStart' },
|
{ what: 'epickerStart' },
|
||||||
url.href,
|
url.href,
|
||||||
[ channel.port2 ]
|
[ channel.port2 ]
|
||||||
);
|
);
|
||||||
|
resolve(iframe);
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
pickerRoot.contentWindow.location = url.href;
|
iframe.contentWindow.location = url.href;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
let pickerFrame = await bootstrap();
|
||||||
|
if ( Boolean(pickerFrame) === false ) {
|
||||||
|
quitPicker();
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
Loading…
Reference in a new issue