mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-10 09:07:54 +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 === null ) { 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
|
||||
|
||||
let blueNodes = [];
|
||||
const roRedNodes = new Map(); // node => current cosmetic filter
|
||||
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 roGreenNodes = new Map(); // node => current exception cosmetic filter (can't toggle)
|
||||
|
||||
const reHasCSSCombinators = /[ >+~]/;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
//const getNodeId = node => nodeToIdMap.get(node) || 0;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const domLayout = (( ) => {
|
||||
const skipTagNames = new Set([
|
||||
'br', 'head', 'link', 'meta', 'script', 'style', 'title'
|
||||
|
@ -670,11 +668,13 @@ const shutdownInspector = ( ) => {
|
|||
passive: true,
|
||||
});
|
||||
contentInspectorChannel.shutdown();
|
||||
vAPI.userStylesheet.remove(inspectorCSS);
|
||||
vAPI.userStylesheet.apply();
|
||||
if ( inspectorFrame === null ) { return; }
|
||||
if ( inspectorFrame ) {
|
||||
inspectorFrame.remove();
|
||||
inspectorFrame = null;
|
||||
}
|
||||
vAPI.userStylesheet.remove(inspectorCSS);
|
||||
vAPI.userStylesheet.apply();
|
||||
vAPI.inspectorFrame = false;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -826,22 +826,22 @@ const contentInspectorChannel = (( ) => {
|
|||
if ( inspectorArgs === null ) { return; }
|
||||
return new Promise(resolve => {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.setAttribute(vAPI.sessionId, '');
|
||||
iframe.setAttribute(inspectorUniqueId, '');
|
||||
document.documentElement.append(iframe);
|
||||
iframe.addEventListener('load', ( ) => {
|
||||
iframe.setAttribute(`${vAPI.sessionId}-loaded`, '');
|
||||
iframe.setAttribute(`${inspectorUniqueId}-loaded`, '');
|
||||
const channel = new MessageChannel();
|
||||
toFramePort = channel.port1;
|
||||
toFramePort.onmessage = ev => {
|
||||
const msg = ev.data || {};
|
||||
if ( msg.what !== 'startInspector' ) { return; }
|
||||
resolve(iframe);
|
||||
};
|
||||
iframe.contentWindow.postMessage(
|
||||
{ what: 'startInspector' },
|
||||
inspectorArgs.inspectorURL,
|
||||
[ channel.port2 ]
|
||||
);
|
||||
resolve(iframe);
|
||||
}, { once: true });
|
||||
iframe.contentWindow.location = inspectorArgs.inspectorURL;
|
||||
});
|
||||
|
@ -859,26 +859,32 @@ const inspectorCSSStyle = [
|
|||
'box-shadow: none',
|
||||
'color-scheme: light dark',
|
||||
'display: block',
|
||||
'filter: none',
|
||||
'height: 100%',
|
||||
'left: 0',
|
||||
'margin: 0',
|
||||
'max-height: none',
|
||||
'max-width: none',
|
||||
'min-height: unset',
|
||||
'min-width: unset',
|
||||
'opacity: 1',
|
||||
'outline: 0',
|
||||
'padding: 0',
|
||||
'pointer-events: none',
|
||||
'position: fixed',
|
||||
'top: 0',
|
||||
'visibility: visible',
|
||||
'transform: none',
|
||||
'visibility: hidden',
|
||||
'width: 100%',
|
||||
'z-index: 2147483647',
|
||||
''
|
||||
].join(' !important;\n');
|
||||
|
||||
const inspectorCSS = `
|
||||
:root > [${vAPI.sessionId}] {
|
||||
:root > [${inspectorUniqueId}] {
|
||||
${inspectorCSSStyle}
|
||||
}
|
||||
:root > [${vAPI.sessionId}-loaded] {
|
||||
:root > [${inspectorUniqueId}-loaded] {
|
||||
visibility: visible !important;
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -30,18 +30,13 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
if ( typeof vAPI !== 'object' || vAPI === null ) {
|
||||
return;
|
||||
}
|
||||
if ( typeof vAPI !== 'object' ) { return; }
|
||||
if ( typeof vAPI === null ) { return; }
|
||||
|
||||
/******************************************************************************/
|
||||
if ( vAPI.pickerFrame ) { return; }
|
||||
vAPI.pickerFrame = true;
|
||||
|
||||
const epickerId = vAPI.randomToken();
|
||||
|
||||
let pickerRoot = document.querySelector(`[${vAPI.sessionId}]`);
|
||||
if ( pickerRoot !== null ) { return; }
|
||||
|
||||
let pickerBootArgs;
|
||||
const pickerUniqueId = vAPI.randomToken();
|
||||
|
||||
const reCosmeticAnchor = /^#(\$|\?|\$\?)?#/;
|
||||
|
||||
|
@ -128,7 +123,7 @@ const highlightElements = function(elems, force) {
|
|||
const islands = [];
|
||||
|
||||
for ( const elem of elems ) {
|
||||
if ( elem === pickerRoot ) { continue; }
|
||||
if ( elem === pickerFrame ) { continue; }
|
||||
targetElements.push(elem);
|
||||
const rect = getElementBoundingClientRect(elem);
|
||||
// Ignore offscreen areas
|
||||
|
@ -554,10 +549,10 @@ const filtersFrom = function(x, y) {
|
|||
// https://www.reddit.com/r/uBlockOrigin/comments/qmjk36/
|
||||
// Extract network candidates first.
|
||||
if ( typeof x === 'number' ) {
|
||||
const magicAttr = `${vAPI.sessionId}-clickblind`;
|
||||
pickerRoot.setAttribute(magicAttr, '');
|
||||
const magicAttr = `${pickerUniqueId}-clickblind`;
|
||||
pickerFrame.setAttribute(magicAttr, '');
|
||||
const elems = document.elementsFromPoint(x, y);
|
||||
pickerRoot.removeAttribute(magicAttr);
|
||||
pickerFrame.removeAttribute(magicAttr);
|
||||
for ( const elem of elems ) {
|
||||
netFilterFromElement(elem);
|
||||
}
|
||||
|
@ -737,7 +732,7 @@ const filterToDOMInterface = (( ) => {
|
|||
}
|
||||
const out = [];
|
||||
for ( const elem of elems ) {
|
||||
if ( elem === pickerRoot ) { continue; }
|
||||
if ( elem === pickerFrame ) { continue; }
|
||||
out.push({ elem, raw, style: vAPI.hideStyle });
|
||||
}
|
||||
return out;
|
||||
|
@ -815,7 +810,7 @@ const filterToDOMInterface = (( ) => {
|
|||
if ( Array.isArray(lastResultset) === false ) { return; }
|
||||
const rootElem = document.documentElement;
|
||||
for ( const { elem, style } of lastResultset ) {
|
||||
if ( elem === pickerRoot ) { continue; }
|
||||
if ( elem === pickerFrame ) { continue; }
|
||||
if ( style === undefined ) { continue; }
|
||||
if ( elem === rootElem && style === vAPI.hideStyle ) { continue; }
|
||||
let styleToken = vAPI.epickerStyleProxies.get(style);
|
||||
|
@ -932,9 +927,9 @@ const elementFromPoint = (( ) => {
|
|||
} else {
|
||||
return null;
|
||||
}
|
||||
if ( !pickerRoot ) { return null; }
|
||||
const magicAttr = `${vAPI.sessionId}-clickblind`;
|
||||
pickerRoot.setAttribute(magicAttr, '');
|
||||
if ( !pickerFrame ) { return null; }
|
||||
const magicAttr = `${pickerUniqueId}-clickblind`;
|
||||
pickerFrame.setAttribute(magicAttr, '');
|
||||
let elem = document.elementFromPoint(x, y);
|
||||
if (
|
||||
elem === null || /* to skip following tests */
|
||||
|
@ -948,7 +943,7 @@ const elementFromPoint = (( ) => {
|
|||
elem = null;
|
||||
}
|
||||
// https://github.com/uBlockOrigin/uBlock-issues/issues/380
|
||||
pickerRoot.removeAttribute(magicAttr);
|
||||
pickerFrame.removeAttribute(magicAttr);
|
||||
return elem;
|
||||
};
|
||||
})();
|
||||
|
@ -1064,7 +1059,7 @@ const onViewportChanged = function() {
|
|||
// Auto-select a specific target, if any, and if possible
|
||||
|
||||
const startPicker = function() {
|
||||
pickerRoot.focus();
|
||||
pickerFrame.focus();
|
||||
|
||||
self.addEventListener('scroll', onViewportChanged, { passive: true });
|
||||
self.addEventListener('resize', onViewportChanged, { passive: true });
|
||||
|
@ -1101,7 +1096,7 @@ const startPicker = function() {
|
|||
if ( attr === undefined ) { return; }
|
||||
const elems = document.getElementsByTagName(tagName);
|
||||
for ( const elem of elems ) {
|
||||
if ( elem === pickerRoot ) { continue; }
|
||||
if ( elem === pickerFrame ) { continue; }
|
||||
const srcs = resourceURLsFromElement(elem);
|
||||
if (
|
||||
(srcs.length !== 0 && srcs.includes(url) === false) ||
|
||||
|
@ -1140,19 +1135,22 @@ const quitPicker = function() {
|
|||
self.removeEventListener('resize', onViewportChanged, { passive: true });
|
||||
self.removeEventListener('keydown', onKeyPressed, true);
|
||||
vAPI.shutdown.remove(quitPicker);
|
||||
if ( pickerFramePort !== null ) {
|
||||
if ( pickerFramePort ) {
|
||||
pickerFramePort.close();
|
||||
pickerFramePort = null;
|
||||
}
|
||||
if ( pickerRoot !== null ) {
|
||||
pickerRoot.remove();
|
||||
pickerRoot = null;
|
||||
if ( pickerFrame ) {
|
||||
pickerFrame.remove();
|
||||
pickerFrame = null;
|
||||
}
|
||||
vAPI.userStylesheet.remove(pickerCSS);
|
||||
vAPI.userStylesheet.apply();
|
||||
vAPI.pickerFrame = false;
|
||||
self.focus();
|
||||
};
|
||||
|
||||
vAPI.shutdown.add(quitPicker);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
const onDialogMessage = function(msg) {
|
||||
|
@ -1232,21 +1230,6 @@ const onDialogMessage = function(msg) {
|
|||
// of the iframe, and cannot interfere with its style properties. However the
|
||||
// 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.
|
||||
const noCosmeticFiltering =
|
||||
vAPI.domFilterer instanceof Object === false ||
|
||||
|
@ -1285,13 +1268,13 @@ const pickerCSSStyle = [
|
|||
|
||||
|
||||
const pickerCSS = `
|
||||
:root > [${vAPI.sessionId}] {
|
||||
:root > [${pickerUniqueId}] {
|
||||
${pickerCSSStyle}
|
||||
}
|
||||
:root > [${vAPI.sessionId}-loaded] {
|
||||
:root > [${pickerUniqueId}-loaded] {
|
||||
visibility: visible !important;
|
||||
}
|
||||
:root [${vAPI.sessionId}-clickblind] {
|
||||
:root [${pickerUniqueId}-clickblind] {
|
||||
pointer-events: none !important;
|
||||
}
|
||||
`;
|
||||
|
@ -1299,38 +1282,53 @@ const pickerCSS = `
|
|||
vAPI.userStylesheet.add(pickerCSS);
|
||||
vAPI.userStylesheet.apply();
|
||||
|
||||
pickerRoot = document.createElement('iframe');
|
||||
pickerRoot.setAttribute(vAPI.sessionId, '');
|
||||
document.documentElement.append(pickerRoot);
|
||||
|
||||
vAPI.shutdown.add(quitPicker);
|
||||
|
||||
let pickerBootArgs;
|
||||
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);
|
||||
url.searchParams.set('epid', epickerId);
|
||||
if ( pickerBootArgs.zap ) {
|
||||
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();
|
||||
pickerFramePort = channel.port1;
|
||||
pickerFramePort.onmessage = ev => {
|
||||
const msg = ev.data || {};
|
||||
onDialogMessage(msg);
|
||||
onDialogMessage(ev.data || {});
|
||||
};
|
||||
pickerFramePort.onmessageerror = ( ) => {
|
||||
quitPicker();
|
||||
};
|
||||
pickerRoot.setAttribute(`${vAPI.sessionId}-loaded`, '');
|
||||
pickerRoot.contentWindow.postMessage(
|
||||
iframe.contentWindow.postMessage(
|
||||
{ what: 'epickerStart' },
|
||||
url.href,
|
||||
[ channel.port2 ]
|
||||
);
|
||||
resolve(iframe);
|
||||
}, { 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