diff options
Diffstat (limited to 'js/popup.js')
-rw-r--r-- | js/popup.js | 1572 |
1 files changed, 786 insertions, 786 deletions
diff --git a/js/popup.js b/js/popup.js index d750997..073f57a 100644 --- a/js/popup.js +++ b/js/popup.js @@ -2,7 +2,7 @@ ηMatrix - a browser extension to black/white list requests. Copyright (C) 2014-2019 Raymond Hill - Copyright (C) 2019-2020 Alessio Vanni + Copyright (C) 2019-2022 Alessio Vanni 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 @@ -17,7 +17,7 @@ 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://libregit.spks.xyz/heckyel/ematrix + Home: https://gitlab.com/vannilla/ematrix uMatrix Home: https://github.com/gorhill/uMatrix */ @@ -29,67 +29,67 @@ // Stuff which is good to do very early so as to avoid visual glitches. (function () { - let paneContentPaddingTop = - vAPI.localStorage.getItem('paneContentPaddingTop'); + let paneContentPaddingTop = + vAPI.localStorage.getItem('paneContentPaddingTop'); let touchDevice = vAPI.localStorage.getItem('touchDevice'); - if (typeof paneContentPaddingTop === 'string') { + if (typeof paneContentPaddingTop === 'string') { document - .querySelector('.paneContent') - .style - .setProperty('padding-top', - paneContentPaddingTop); - } - - /* This is for CSS */ - if (touchDevice === 'true') { + .querySelector('.paneContent') + .style + .setProperty('padding-top', + paneContentPaddingTop); + } + + /* This is for CSS */ + if (touchDevice === 'true') { document.body.setAttribute('data-touch', 'true'); - } else { + } else { document.addEventListener('touchstart', function onTouched(ev) { - document.removeEventListener(ev.type, onTouched); - document.body.setAttribute('data-touch', 'true'); - vAPI.localStorage.setItem('touchDevice', 'true'); - resizePopup(); + document.removeEventListener(ev.type, onTouched); + document.body.setAttribute('data-touch', 'true'); + vAPI.localStorage.setItem('touchDevice', 'true'); + resizePopup(); }); - } + } })(); let popupWasResized = function () { - document.body.setAttribute('data-resize-popup', ''); + document.body.setAttribute('data-resize-popup', ''); }; let resizePopup = (function () { - let timer; + let timer; - let fix = function () { + let fix = function () { timer = undefined; let doc = document; // Manually adjust the position of the main matrix according to the // height of the toolbar/matrix header. let paddingTop = - (doc.querySelector('.paneHead').clientHeight + 2) + 'px'; + (doc.querySelector('.paneHead').clientHeight + 2) + 'px'; let paneContent = doc.querySelector('.paneContent'); if (paddingTop !== paneContent.style.paddingTop) { - paneContent.style.setProperty('padding-top', paddingTop); - vAPI.localStorage.setItem('paneContentPaddingTop', paddingTop); + paneContent.style.setProperty('padding-top', paddingTop); + vAPI.localStorage.setItem('paneContentPaddingTop', paddingTop); } document - .body - .classList - .toggle('hConstrained', - window.innerWidth < document.body.clientWidth); + .body + .classList + .toggle('hConstrained', + window.innerWidth < document.body.clientWidth); popupWasResized(); - }; + }; - return function () { + return function () { if (timer !== undefined) { - clearTimeout(timer); + clearTimeout(timer); } timer = vAPI.setTimeout(fix, 97); - }; + }; })(); // Must be consistent with definitions in matrix.js @@ -106,15 +106,15 @@ let matrixCellHotspots = null; let matrixHeaderPrettyNames = { - 'all': '', - 'cookie': '', - 'css': '', - 'image': '', - 'media': '', - 'script': '', - 'xhr': '', - 'frame': '', - 'other': '' + 'all': '', + 'cookie': '', + 'css': '', + 'image': '', + 'media': '', + 'script': '', + 'xhr': '', + 'frame': '', + 'other': '' }; let firstPartyLabel = ''; @@ -122,30 +122,30 @@ let expandosIdGenerator = 1; let nodeToExpandosMap = (function () { - if (typeof window.Map === 'function') { + if (typeof window.Map === 'function') { return new window.Map(); - } + } })(); let expandosFromNode = function (node) { - if (node instanceof HTMLElement === false - && typeof node.nodeAt === 'function') { + if (node instanceof HTMLElement === false + && typeof node.nodeAt === 'function') { node = node.nodeAt(0); - } - if (nodeToExpandosMap) { + } + if (nodeToExpandosMap) { let expandosId = node.getAttribute('data-expandos'); if (!expandosId) { - expandosId = '' + (expandosIdGenerator++); - node.setAttribute('data-expandos', expandosId); + expandosId = '' + (expandosIdGenerator++); + node.setAttribute('data-expandos', expandosId); } let expandos = nodeToExpandosMap.get(expandosId); if (expandos === undefined) { - expandos = Object.create(null); - nodeToExpandosMap.set(expandosId, expandos); + expandos = Object.create(null); + nodeToExpandosMap.set(expandosId, expandos); } return expandos; - } - return node; + } + return node; }; function getUserSetting(setting) { @@ -153,28 +153,28 @@ } function setUserSetting(setting, value) { - matrixSnapshot.userSettings[setting] = value; - vAPI.messaging.send('popup.js', { + matrixSnapshot.userSettings[setting] = value; + vAPI.messaging.send('popup.js', { what: 'userSettings', name: setting, value: value - }); + }); } function getUISetting(setting) { - let r = vAPI.localStorage.getItem(setting); - if (typeof r !== 'string') { + let r = vAPI.localStorage.getItem(setting); + if (typeof r !== 'string') { return undefined; - } - return JSON.parse(r); + } + return JSON.parse(r); } function setUISetting(setting, value) { - vAPI.localStorage.setItem(setting, JSON.stringify(value)); + vAPI.localStorage.setItem(setting, JSON.stringify(value)); } function updateMatrixSnapshot() { - matrixSnapshotPoller.pollNow(); + matrixSnapshotPoller.pollNow(); } // For display purpose, create four distinct groups of rows: @@ -186,162 +186,162 @@ function getGroupStats() { - // Try to not reshuffle groups around while popup is opened if - // no new hostname added. - let latestDomainListSnapshot = - Object.keys(matrixSnapshot.rows).sort().join(); - if (latestDomainListSnapshot === allHostnamesSnapshot) { + // Try to not reshuffle groups around while popup is opened if + // no new hostname added. + let latestDomainListSnapshot = + Object.keys(matrixSnapshot.rows).sort().join(); + if (latestDomainListSnapshot === allHostnamesSnapshot) { return groupsSnapshot; - } - allHostnamesSnapshot = latestDomainListSnapshot; - - // First, group according to whether at least one node in the domain - // hierarchy is white or blacklisted - let pageDomain = matrixSnapshot.domain; - let rows = matrixSnapshot.rows; - let anyTypeOffset = matrixSnapshot.headerIndices.get('*'); - let hostname, domain; - let row, color, count; - let domainToGroupMap = {}; - - // These have hard-coded position which cannot be overriden - domainToGroupMap['1st-party'] = 0; - domainToGroupMap[pageDomain] = 1; - - // 1st pass: domain wins if it has an explicit rule or a count - for (hostname in rows) { + } + allHostnamesSnapshot = latestDomainListSnapshot; + + // First, group according to whether at least one node in the domain + // hierarchy is white or blacklisted + let pageDomain = matrixSnapshot.domain; + let rows = matrixSnapshot.rows; + let anyTypeOffset = matrixSnapshot.headerIndices.get('*'); + let hostname, domain; + let row, color, count; + let domainToGroupMap = {}; + + // These have hard-coded position which cannot be overriden + domainToGroupMap['1st-party'] = 0; + domainToGroupMap[pageDomain] = 1; + + // 1st pass: domain wins if it has an explicit rule or a count + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } if (hostname === '*' || hostname === '1st-party') { - continue; + continue; } domain = rows[hostname].domain; if (domain === pageDomain || hostname !== domain) { - continue; + continue; } row = rows[domain]; color = row.temporary[anyTypeOffset]; if (color === DarkGreen) { - domainToGroupMap[domain] = 2; - continue; + domainToGroupMap[domain] = 2; + continue; } if (color === DarkRed) { - domainToGroupMap[domain] = 4; - continue; + domainToGroupMap[domain] = 4; + continue; } count = row.counts[anyTypeOffset]; if (count !== 0) { - domainToGroupMap[domain] = 3; - continue; + domainToGroupMap[domain] = 3; + continue; } - } + } - // 2nd pass: green wins - for (hostname in rows) { + // 2nd pass: green wins + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; domain = row.domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } color = row.temporary[anyTypeOffset]; if (color === DarkGreen) { - domainToGroupMap[domain] = 2; + domainToGroupMap[domain] = 2; } - } + } - // 3rd pass: gray with count wins - for (hostname in rows) { + // 3rd pass: gray with count wins + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; domain = row.domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } color = row.temporary[anyTypeOffset]; count = row.counts[anyTypeOffset]; if ( color !== DarkRed && count !== 0 ) { - domainToGroupMap[domain] = 3; + domainToGroupMap[domain] = 3; } - } + } - // 4th pass: red wins whatever is left - for (hostname in rows) { + // 4th pass: red wins whatever is left + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; domain = row.domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } color = row.temporary[anyTypeOffset]; if (color === DarkRed) { - domainToGroupMap[domain] = 4; + domainToGroupMap[domain] = 4; } - } + } - // 5th pass: gray wins whatever is left - for (hostname in rows) { + // 5th pass: gray wins whatever is left + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } domain = rows[hostname].domain; if (domainToGroupMap.hasOwnProperty(domain)) { - continue; + continue; } domainToGroupMap[domain] = 3; - } + } - // Last pass: put each domain in a group - let groups = [ - {}, {}, {}, {}, {} - ]; + // Last pass: put each domain in a group + let groups = [ + {}, {}, {}, {}, {} + ]; - for (hostname in rows) { + for (hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } if ( hostname === '*' ) { - continue; + continue; } domain = rows[hostname].domain; let groupIndex = domainToGroupMap[domain]; let group = groups[groupIndex]; if (group.hasOwnProperty(domain) === false) { - group[domain] = {}; + group[domain] = {}; } group[domain][hostname] = true; - } + } - groupsSnapshot = groups; + groupsSnapshot = groups; - return groups; + return groups; } // helpers function getTemporaryColor(hostname, type) { - return matrixSnapshot - .rows[hostname] - .temporary[matrixSnapshot.headerIndices.get(type)]; + return matrixSnapshot + .rows[hostname] + .temporary[matrixSnapshot.headerIndices.get(type)]; } function getPermanentColor(hostname, type) { - return matrixSnapshot - .rows[hostname] - .permanent[matrixSnapshot.headerIndices.get(type)]; + return matrixSnapshot + .rows[hostname] + .permanent[matrixSnapshot.headerIndices.get(type)]; } function addCellClass(cell, hostname, type) { - let cl = cell.classList; - cl.add('matCell'); - cl.add('t' + getTemporaryColor(hostname, type).toString(16)); - cl.add('p' + getPermanentColor(hostname, type).toString(16)); + let cl = cell.classList; + cl.add('matCell'); + cl.add('t' + getTemporaryColor(hostname, type).toString(16)); + cl.add('p' + getPermanentColor(hostname, type).toString(16)); } // This is required for when we update the matrix while it is open: @@ -349,118 +349,118 @@ // want to lose all his hardwork. function getCollapseState(domain) { - let states = getUISetting('popupCollapseSpecificDomains'); - if (typeof states === 'object' && states[domain] !== undefined) { + let states = getUISetting('popupCollapseSpecificDomains'); + if (typeof states === 'object' && states[domain] !== undefined) { return states[domain]; - } - return matrixSnapshot.collapseAllDomains === true; + } + return matrixSnapshot.collapseAllDomains === true; } function toggleCollapseState(elem) { - if (elem.ancestors('#matHead.collapsible').length > 0) { + if (elem.ancestors('#matHead.collapsible').length > 0) { toggleMainCollapseState(elem); - } else { + } else { toggleSpecificCollapseState(elem); - } - popupWasResized(); + } + popupWasResized(); } function toggleMainCollapseState(uelem) { - let matHead = - uelem.ancestors('#matHead.collapsible').toggleClass('collapsed'); - let collapsed = - matrixSnapshot.collapseAllDomains = matHead.hasClass('collapsed'); - - uDom('#matList .matSection.collapsible') - .toggleClass('collapsed', collapsed); - setUserSetting('popupCollapseAllDomains', collapsed); - - let specificCollapseStates = - getUISetting('popupCollapseSpecificDomains') || {}; - let domains = Object.keys(specificCollapseStates); - for (let i=domains.length-1; i>=0; --i) { + let matHead = + uelem.ancestors('#matHead.collapsible').toggleClass('collapsed'); + let collapsed = + matrixSnapshot.collapseAllDomains = matHead.hasClass('collapsed'); + + uDom('#matList .matSection.collapsible') + .toggleClass('collapsed', collapsed); + setUserSetting('popupCollapseAllDomains', collapsed); + + let specificCollapseStates = + getUISetting('popupCollapseSpecificDomains') || {}; + let domains = Object.keys(specificCollapseStates); + for (let i=domains.length-1; i>=0; --i) { let domain = domains[i]; if (specificCollapseStates[domain] === collapsed) { - delete specificCollapseStates[domain]; + delete specificCollapseStates[domain]; } - } - setUISetting('popupCollapseSpecificDomains', specificCollapseStates); + } + setUISetting('popupCollapseSpecificDomains', specificCollapseStates); } function toggleSpecificCollapseState(uelem) { - // Remember collapse state forever, but only if it is different - // from main collapse switch. - let section = - uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'); + // Remember collapse state forever, but only if it is different + // from main collapse switch. + let section = + uelem.ancestors('.matSection.collapsible').toggleClass('collapsed'); let domain = expandosFromNode(section).domain; let collapsed = section.hasClass('collapsed'); let mainCollapseState = matrixSnapshot.collapseAllDomains === true; let specificCollapseStates = - getUISetting('popupCollapseSpecificDomains') || {}; + getUISetting('popupCollapseSpecificDomains') || {}; - if (collapsed !== mainCollapseState) { + if (collapsed !== mainCollapseState) { specificCollapseStates[domain] = collapsed; setUISetting('popupCollapseSpecificDomains', - specificCollapseStates); - } else if (specificCollapseStates[domain] !== undefined) { + specificCollapseStates); + } else if (specificCollapseStates[domain] !== undefined) { delete specificCollapseStates[domain]; setUISetting('popupCollapseSpecificDomains', - specificCollapseStates); - } + specificCollapseStates); + } } // Update count value of matrix cells(s) function updateMatrixCounts() { - let matCells = uDom('.matrix .matRow.rw > .matCell'); + let matCells = uDom('.matrix .matRow.rw > .matCell'); let matRow, matCell, count, counts; let headerIndices = matrixSnapshot.headerIndices; let rows = matrixSnapshot.rows; let expandos; - for (let i=matCells.length-1; i>=0; --i) { + for (let i=matCells.length-1; i>=0; --i) { matCell = matCells.nodeAt(i); expandos = expandosFromNode(matCell); if (expandos.hostname === '*' || expandos.reqType === '*') { - continue; + continue; } matRow = matCell.parentNode; counts = matRow.classList.contains('meta') ? 'totals' : 'counts'; count = rows[expandos.hostname][counts][headerIndices - .get(expandos.reqType)]; + .get(expandos.reqType)]; if (count === expandos.count) { - continue; - } + continue; + } expandos.count = count; matCell.textContent = cellTextFromCount(count); - } + } } function cellTextFromCount(count) { - if (count === 0) { - return '\u00A0'; - } + if (count === 0) { + return '\u00A0'; + } - if (count < 100) { - return count; - } + if (count < 100) { + return count; + } - return '99+'; + return '99+'; } // Update color of matrix cells(s) // Color changes when rules change function updateMatrixColors() { - let cells = uDom('.matrix .matRow.rw > .matCell').removeClass(); + let cells = uDom('.matrix .matRow.rw > .matCell').removeClass(); let cell, expandos; - for (let i=cells.length-1; i>=0; --i) { + for (let i=cells.length-1; i>=0; --i) { cell = cells.nodeAt(i); expandos = expandosFromNode(cell); addCellClass(cell, expandos.hostname, expandos.reqType); - } + } - popupWasResized(); + popupWasResized(); } // Update behavior of matrix: @@ -470,78 +470,78 @@ // - It is not part of group 3 (blacklisted hostnames) function updateMatrixBehavior() { - matrixList = matrixList || uDom('#matList'); - let sections = matrixList.descendants('.matSection'); - let section, subdomainRows, subdomainRow; - for (let i=sections.length-1; i>=0; --i) { + matrixList = matrixList || uDom('#matList'); + let sections = matrixList.descendants('.matSection'); + let section, subdomainRows, subdomainRow; + for (let i=sections.length-1; i>=0; --i) { section = sections.at(i); subdomainRows = section.descendants('.l2:not(.g4)'); for (let j=subdomainRows.length-1; j>=0; --j) { - subdomainRow = subdomainRows.at(j); - subdomainRow.toggleClass('collapsible', - subdomainRow - .descendants('.t81,.t82') - .length === 0); + subdomainRow = subdomainRows.at(j); + subdomainRow.toggleClass('collapsible', + subdomainRow + .descendants('.t81,.t82') + .length === 0); } section.toggleClass('collapsible', - subdomainRows.filter('.collapsible').length > 0); - } + subdomainRows.filter('.collapsible').length > 0); + } } // handle user interaction with filters function getCellAction(hostname, type, leaning) { - let temporaryColor = getTemporaryColor(hostname, type); - let hue = temporaryColor & 0x03; + let temporaryColor = getTemporaryColor(hostname, type); + let hue = temporaryColor & 0x03; - // Special case: root toggle only between two states - if (type === '*' && hostname === '*') { + // Special case: root toggle only between two states + if (type === '*' && hostname === '*') { return hue === Green ? - 'blacklistMatrixCell' : - 'whitelistMatrixCell'; - } + 'blacklistMatrixCell' : + 'whitelistMatrixCell'; + } - // When explicitly blocked/allowed, can only graylist - let saturation = temporaryColor & 0x80; - if (saturation === Dark) { + // When explicitly blocked/allowed, can only graylist + let saturation = temporaryColor & 0x80; + if (saturation === Dark) { return 'graylistMatrixCell'; - } + } - return leaning === 'whitelisting' ? - 'whitelistMatrixCell' : - 'blacklistMatrixCell'; + return leaning === 'whitelisting' ? + 'whitelistMatrixCell' : + 'blacklistMatrixCell'; } function handleFilter(button, leaning) { - // our parent cell knows who we are - let cell = button.ancestors('div.matCell'); + // our parent cell knows who we are + let cell = button.ancestors('div.matCell'); let expandos = expandosFromNode(cell); let type = expandos.reqType; let desHostname = expandos.hostname; - // https://github.com/gorhill/uMatrix/issues/24 - // No hostname can happen -- like with blacklist meta row - if (desHostname === '') { + // https://github.com/gorhill/uMatrix/issues/24 + // No hostname can happen -- like with blacklist meta row + if (desHostname === '') { return; - } + } - let request = { + let request = { what: getCellAction(desHostname, type, leaning), srcHostname: matrixSnapshot.scope, desHostname: desHostname, type: type - }; + }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } function handleWhitelistFilter(button) { - handleFilter(button, 'whitelisting'); + handleFilter(button, 'whitelisting'); } function handleBlacklistFilter(button) { - handleFilter(button, 'blacklisting'); + handleFilter(button, 'blacklisting'); } let matrixRowPool = []; @@ -551,299 +551,299 @@ let matrixList = null; let startMatrixUpdate = function () { - matrixList = matrixList || uDom('#matList'); - matrixList.detach(); - let rows = matrixList.descendants('.matRow'); - rows.detach(); - matrixRowPool = matrixRowPool.concat(rows.toArray()); - let sections = matrixList.descendants('.matSection'); - sections.detach(); - matrixSectionPool = matrixSectionPool.concat(sections.toArray()); - let groups = matrixList.descendants('.matGroup'); - groups.detach(); - matrixGroupPool = matrixGroupPool.concat(groups.toArray()); + matrixList = matrixList || uDom('#matList'); + matrixList.detach(); + let rows = matrixList.descendants('.matRow'); + rows.detach(); + matrixRowPool = matrixRowPool.concat(rows.toArray()); + let sections = matrixList.descendants('.matSection'); + sections.detach(); + matrixSectionPool = matrixSectionPool.concat(sections.toArray()); + let groups = matrixList.descendants('.matGroup'); + groups.detach(); + matrixGroupPool = matrixGroupPool.concat(groups.toArray()); }; let endMatrixUpdate = function () { - // https://github.com/gorhill/httpswitchboard/issues/246 If - // the matrix has no rows, we need to insert a dummy one, - // invisible, to ensure the extension pop-up is properly - // sized. This is needed because the header pane's `position` - // property is `fixed`, which means it doesn't affect layout - // size, hence the matrix header row will be truncated. - if (matrixSnapshot.rowCount <= 1) { + // https://github.com/gorhill/httpswitchboard/issues/246 If + // the matrix has no rows, we need to insert a dummy one, + // invisible, to ensure the extension pop-up is properly + // sized. This is needed because the header pane's `position` + // property is `fixed`, which means it doesn't affect layout + // size, hence the matrix header row will be truncated. + if (matrixSnapshot.rowCount <= 1) { matrixList.append(createMatrixRow().css('visibility', 'hidden')); - } + } - updateMatrixBehavior(); - matrixList.css('display', ''); - matrixList.appendTo('.paneContent'); + updateMatrixBehavior(); + matrixList.css('display', ''); + matrixList.appendTo('.paneContent'); }; let createMatrixGroup = function () { - let group = matrixGroupPool.pop(); - if (group) { + let group = matrixGroupPool.pop(); + if (group) { return uDom(group).removeClass().addClass('matGroup'); - } - return uDom(document.createElement('div')).addClass('matGroup'); + } + return uDom(document.createElement('div')).addClass('matGroup'); }; let createMatrixSection = function () { - let section = matrixSectionPool.pop(); - if (section) { + let section = matrixSectionPool.pop(); + if (section) { return uDom(section).removeClass().addClass('matSection'); - } - return uDom(document.createElement('div')).addClass('matSection'); + } + return uDom(document.createElement('div')).addClass('matSection'); }; let createMatrixRow = function () { - let row = matrixRowPool.pop(); - if (row) { + let row = matrixRowPool.pop(); + if (row) { row.style.visibility = ''; row = uDom(row); row.descendants('.matCell').removeClass().addClass('matCell'); row.removeClass().addClass('matRow'); return row; - } + } - if (matrixRowTemplate === null) { + if (matrixRowTemplate === null) { matrixRowTemplate = uDom('#templates .matRow'); - } + } - return matrixRowTemplate.clone(); + return matrixRowTemplate.clone(); }; function renderMatrixHeaderRow() { - let matHead = uDom('#matHead.collapsible'); - matHead.toggleClass('collapsed', - matrixSnapshot.collapseAllDomains === true); - - let cells = matHead.descendants('.matCell') - let cell = cells.nodeAt(0); - let expandos = expandosFromNode(cell); - expandos.reqType = '*'; - expandos.hostname = '*'; - addCellClass(cell, '*', '*'); - - cell = cells.nodeAt(1); - expandos = expandosFromNode(cell); - expandos.reqType = 'cookie'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'cookie'); - - cell = cells.nodeAt(2); - expandos = expandosFromNode(cell); - expandos.reqType = 'css'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'css'); - - cell = cells.nodeAt(3); - expandos = expandosFromNode(cell); - expandos.reqType = 'image'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'image'); - - cell = cells.nodeAt(4); - expandos = expandosFromNode(cell); - expandos.reqType = 'media'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'media'); - - cell = cells.nodeAt(5); - expandos = expandosFromNode(cell); - expandos.reqType = 'script'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'script'); - - cell = cells.nodeAt(6); - expandos = expandosFromNode(cell); - expandos.reqType = 'xhr'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'xhr'); - - cell = cells.nodeAt(7); - expandos = expandosFromNode(cell); - expandos.reqType = 'frame'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'frame'); - - cell = cells.nodeAt(8); - expandos = expandosFromNode(cell); - expandos.reqType = 'other'; - expandos.hostname = '*'; - addCellClass(cell, '*', 'other'); - - uDom('#matHead .matRow').css('display', ''); + let matHead = uDom('#matHead.collapsible'); + matHead.toggleClass('collapsed', + matrixSnapshot.collapseAllDomains === true); + + let cells = matHead.descendants('.matCell') + let cell = cells.nodeAt(0); + let expandos = expandosFromNode(cell); + expandos.reqType = '*'; + expandos.hostname = '*'; + addCellClass(cell, '*', '*'); + + cell = cells.nodeAt(1); + expandos = expandosFromNode(cell); + expandos.reqType = 'cookie'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'cookie'); + + cell = cells.nodeAt(2); + expandos = expandosFromNode(cell); + expandos.reqType = 'css'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'css'); + + cell = cells.nodeAt(3); + expandos = expandosFromNode(cell); + expandos.reqType = 'image'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'image'); + + cell = cells.nodeAt(4); + expandos = expandosFromNode(cell); + expandos.reqType = 'media'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'media'); + + cell = cells.nodeAt(5); + expandos = expandosFromNode(cell); + expandos.reqType = 'script'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'script'); + + cell = cells.nodeAt(6); + expandos = expandosFromNode(cell); + expandos.reqType = 'xhr'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'xhr'); + + cell = cells.nodeAt(7); + expandos = expandosFromNode(cell); + expandos.reqType = 'frame'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'frame'); + + cell = cells.nodeAt(8); + expandos = expandosFromNode(cell); + expandos.reqType = 'other'; + expandos.hostname = '*'; + addCellClass(cell, '*', 'other'); + + uDom('#matHead .matRow').css('display', ''); } function renderMatrixCellDomain(cell, domain) { - let expandos = expandosFromNode(cell); - expandos.hostname = domain; - expandos.reqType = '*'; - addCellClass(cell.nodeAt(0), domain, '*'); + let expandos = expandosFromNode(cell); + expandos.hostname = domain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), domain, '*'); - let contents = cell.contents(); - contents.nodeAt(0).textContent = domain === '1st-party' ? + let contents = cell.contents(); + contents.nodeAt(0).textContent = domain === '1st-party' ? firstPartyLabel : Punycode.toUnicode(domain); - contents.nodeAt(1).textContent = ' '; + contents.nodeAt(1).textContent = ' '; } function renderMatrixCellSubdomain(cell, domain, subomain) { - let expandos = expandosFromNode(cell); - expandos.hostname = subomain; - expandos.reqType = '*'; - addCellClass(cell.nodeAt(0), subomain, '*'); + let expandos = expandosFromNode(cell); + expandos.hostname = subomain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), subomain, '*'); - let contents = cell.contents(); - contents.nodeAt(0).textContent = - Punycode.toUnicode(subomain.slice(0, - subomain.lastIndexOf(domain)-1)) - + '.'; - contents.nodeAt(1).textContent = Punycode.toUnicode(domain); + let contents = cell.contents(); + contents.nodeAt(0).textContent = + Punycode.toUnicode(subomain.slice(0, + subomain.lastIndexOf(domain)-1)) + + '.'; + contents.nodeAt(1).textContent = Punycode.toUnicode(domain); } function renderMatrixMetaCellDomain(cell, domain) { - let expandos = expandosFromNode(cell); - expandos.hostname = domain; - expandos.reqType = '*'; - addCellClass(cell.nodeAt(0), domain, '*'); + let expandos = expandosFromNode(cell); + expandos.hostname = domain; + expandos.reqType = '*'; + addCellClass(cell.nodeAt(0), domain, '*'); - let contents = cell.contents(); - contents.nodeAt(0).textContent = '\u2217.' + Punycode.toUnicode(domain); - contents.nodeAt(1).textContent = ' '; + let contents = cell.contents(); + contents.nodeAt(0).textContent = '\u2217.' + Punycode.toUnicode(domain); + contents.nodeAt(1).textContent = ' '; } function renderMatrixCellType(cell, hostname, type, count) { - let node = cell.nodeAt(0); + let node = cell.nodeAt(0); let expandos = expandosFromNode(node); - expandos.hostname = hostname; - expandos.reqType = type; - expandos.count = count; - addCellClass(node, hostname, type); - node.textContent = cellTextFromCount(count); + expandos.hostname = hostname; + expandos.reqType = type; + expandos.count = count; + addCellClass(node, hostname, type); + node.textContent = cellTextFromCount(count); } function renderMatrixCellTypes(cells, hostname, countName) { - let counts = matrixSnapshot.rows[hostname][countName]; - let headerIndices = matrixSnapshot.headerIndices; - renderMatrixCellType(cells.at(1), hostname, 'cookie', - counts[headerIndices.get('cookie')]); - renderMatrixCellType(cells.at(2), hostname, 'css', - counts[headerIndices.get('css')]); - renderMatrixCellType(cells.at(3), hostname, 'image', - counts[headerIndices.get('image')]); - renderMatrixCellType(cells.at(4), hostname, 'media', - counts[headerIndices.get('media')]); - renderMatrixCellType(cells.at(5), hostname, 'script', - counts[headerIndices.get('script')]); - renderMatrixCellType(cells.at(6), hostname, 'xhr', - counts[headerIndices.get('xhr')]); - renderMatrixCellType(cells.at(7), hostname, 'frame', - counts[headerIndices.get('frame')]); - renderMatrixCellType(cells.at(8), hostname, 'other', - counts[headerIndices.get('other')]); + let counts = matrixSnapshot.rows[hostname][countName]; + let headerIndices = matrixSnapshot.headerIndices; + renderMatrixCellType(cells.at(1), hostname, 'cookie', + counts[headerIndices.get('cookie')]); + renderMatrixCellType(cells.at(2), hostname, 'css', + counts[headerIndices.get('css')]); + renderMatrixCellType(cells.at(3), hostname, 'image', + counts[headerIndices.get('image')]); + renderMatrixCellType(cells.at(4), hostname, 'media', + counts[headerIndices.get('media')]); + renderMatrixCellType(cells.at(5), hostname, 'script', + counts[headerIndices.get('script')]); + renderMatrixCellType(cells.at(6), hostname, 'xhr', + counts[headerIndices.get('xhr')]); + renderMatrixCellType(cells.at(7), hostname, 'frame', + counts[headerIndices.get('frame')]); + renderMatrixCellType(cells.at(8), hostname, 'other', + counts[headerIndices.get('other')]); } function makeMatrixRowDomain(domain) { - let matrixRow = createMatrixRow().addClass('rw'); - let cells = matrixRow.descendants('.matCell'); - renderMatrixCellDomain(cells.at(0), domain); - renderMatrixCellTypes(cells, domain, 'counts'); - return matrixRow; + let matrixRow = createMatrixRow().addClass('rw'); + let cells = matrixRow.descendants('.matCell'); + renderMatrixCellDomain(cells.at(0), domain); + renderMatrixCellTypes(cells, domain, 'counts'); + return matrixRow; } function makeMatrixRowSubdomain(domain, subdomain) { - let matrixRow = createMatrixRow().addClass('rw'); - let cells = matrixRow.descendants('.matCell'); - renderMatrixCellSubdomain(cells.at(0), domain, subdomain); - renderMatrixCellTypes(cells, subdomain, 'counts'); - return matrixRow; + let matrixRow = createMatrixRow().addClass('rw'); + let cells = matrixRow.descendants('.matCell'); + renderMatrixCellSubdomain(cells.at(0), domain, subdomain); + renderMatrixCellTypes(cells, subdomain, 'counts'); + return matrixRow; } function makeMatrixMetaRowDomain(domain) { - let matrixRow = createMatrixRow().addClass('rw'); - let cells = matrixRow.descendants('.matCell'); - renderMatrixMetaCellDomain(cells.at(0), domain); - renderMatrixCellTypes(cells, domain, 'totals'); - return matrixRow; + let matrixRow = createMatrixRow().addClass('rw'); + let cells = matrixRow.descendants('.matCell'); + renderMatrixMetaCellDomain(cells.at(0), domain); + renderMatrixCellTypes(cells, domain, 'totals'); + return matrixRow; } function renderMatrixMetaCellType(cell, count) { - // https://github.com/gorhill/uMatrix/issues/24 - // Don't forget to reset cell properties - let node = cell.nodeAt(0); + // https://github.com/gorhill/uMatrix/issues/24 + // Don't forget to reset cell properties + let node = cell.nodeAt(0); let expandos = expandosFromNode(node); - expandos.hostname = ''; - expandos.reqType = ''; - expandos.count = count; - cell.addClass('t1'); - node.textContent = cellTextFromCount(count); + expandos.hostname = ''; + expandos.reqType = ''; + expandos.count = count; + cell.addClass('t1'); + node.textContent = cellTextFromCount(count); } function makeMatrixMetaRow(totals) { - let headerIndices = matrixSnapshot.headerIndices; + let headerIndices = matrixSnapshot.headerIndices; let matrixRow = createMatrixRow().at(0).addClass('ro'); let cells = matrixRow.descendants('.matCell'); let contents = cells.at(0).addClass('t81').contents(); let expandos = expandosFromNode(cells.nodeAt(0)); - expandos.hostname = ''; - expandos.reqType = '*'; - contents.nodeAt(0).textContent = ' '; - contents.nodeAt(1).textContent = - blacklistedHostnamesLabel - .replace('{{count}}', - totals[headerIndices.get('*')].toLocaleString()); - - renderMatrixMetaCellType(cells.at(1), - totals[headerIndices.get('cookie')]); - renderMatrixMetaCellType(cells.at(2), - totals[headerIndices.get('css')]); - renderMatrixMetaCellType(cells.at(3), - totals[headerIndices.get('image')]); - renderMatrixMetaCellType(cells.at(4), - totals[headerIndices.get('media')]); - renderMatrixMetaCellType(cells.at(5), - totals[headerIndices.get('script')]); - renderMatrixMetaCellType(cells.at(6), - totals[headerIndices.get('xhr')]); - renderMatrixMetaCellType(cells.at(7), - totals[headerIndices.get('frame')]); - renderMatrixMetaCellType(cells.at(8), - totals[headerIndices.get('other')]); - return matrixRow; + expandos.hostname = ''; + expandos.reqType = '*'; + contents.nodeAt(0).textContent = ' '; + contents.nodeAt(1).textContent = + blacklistedHostnamesLabel + .replace('{{count}}', + totals[headerIndices.get('*')].toLocaleString()); + + renderMatrixMetaCellType(cells.at(1), + totals[headerIndices.get('cookie')]); + renderMatrixMetaCellType(cells.at(2), + totals[headerIndices.get('css')]); + renderMatrixMetaCellType(cells.at(3), + totals[headerIndices.get('image')]); + renderMatrixMetaCellType(cells.at(4), + totals[headerIndices.get('media')]); + renderMatrixMetaCellType(cells.at(5), + totals[headerIndices.get('script')]); + renderMatrixMetaCellType(cells.at(6), + totals[headerIndices.get('xhr')]); + renderMatrixMetaCellType(cells.at(7), + totals[headerIndices.get('frame')]); + renderMatrixMetaCellType(cells.at(8), + totals[headerIndices.get('other')]); + return matrixRow; } function computeMatrixGroupMetaStats(group) { - let headerIndices = matrixSnapshot.headerIndices; + let headerIndices = matrixSnapshot.headerIndices; let anyTypeIndex = headerIndices.get('*'); let totals = new Array(headerIndices.size); for (let i=headerIndices.size-1; i>=0; --i) { totals[i] = 0; - } + } - let rows = matrixSnapshot.rows; - let row; - for (let hostname in rows) { + let rows = matrixSnapshot.rows; + let row; + for (let hostname in rows) { if (rows.hasOwnProperty(hostname) === false) { - continue; + continue; } row = rows[hostname]; if (group.hasOwnProperty(row.domain) === false) { - continue; + continue; } if (row.counts[anyTypeIndex] === 0) { - continue; + continue; } totals[0] += 1; for (let i=1; i<headerIndices.size; ++i) { - totals[i] += row.counts[i]; + totals[i] += row.counts[i]; } - } + } - return totals; + return totals; } // Compare hostname helper, to order hostname in a logical manner: @@ -851,667 +851,667 @@ // named hostname function hostnameCompare(a, b) { - // Normalize: most significant parts first - if (!a.match(/^\d+(\.\d+){1,3}$/)) { + // Normalize: most significant parts first + if (!a.match(/^\d+(\.\d+){1,3}$/)) { let aa = a.split('.'); a = aa.slice(-2).concat(aa.slice(0,-2).reverse()).join('.'); - } + } - if (!b.match(/^\d+(\.\d+){1,3}$/)) { + if (!b.match(/^\d+(\.\d+){1,3}$/)) { let bb = b.split('.'); b = bb.slice(-2).concat(bb.slice(0,-2).reverse()).join('.'); - } + } - return a.localeCompare(b); + return a.localeCompare(b); } function makeMatrixGroup0SectionDomain() { - return makeMatrixRowDomain('1st-party').addClass('g0 l1'); + return makeMatrixRowDomain('1st-party').addClass('g0 l1'); } function makeMatrixGroup0Section() { - let domainDiv = createMatrixSection(); - expandosFromNode(domainDiv).domain = '1st-party'; - makeMatrixGroup0SectionDomain().appendTo(domainDiv); - return domainDiv; + let domainDiv = createMatrixSection(); + expandosFromNode(domainDiv).domain = '1st-party'; + makeMatrixGroup0SectionDomain().appendTo(domainDiv); + return domainDiv; } function makeMatrixGroup0() { - // Show literal "1st-party" row only if there is - // at least one 1st-party hostname - if (Object.keys(groupsSnapshot[1]).length === 0) { + // Show literal "1st-party" row only if there is + // at least one 1st-party hostname + if (Object.keys(groupsSnapshot[1]).length === 0) { return; - } - let groupDiv = createMatrixGroup().addClass('g0'); - makeMatrixGroup0Section().appendTo(groupDiv); - groupDiv.appendTo(matrixList); + } + let groupDiv = createMatrixGroup().addClass('g0'); + makeMatrixGroup0Section().appendTo(groupDiv); + groupDiv.appendTo(matrixList); } function makeMatrixGroup1SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g1 l1'); + return makeMatrixRowDomain(domain).addClass('g1 l1'); } function makeMatrixGroup1SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g1 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g1 l2'); } function makeMatrixGroup1SectionMetaDomain(domain) { - return makeMatrixMetaRowDomain(domain).addClass('g1 l1 meta'); + return makeMatrixMetaRowDomain(domain).addClass('g1 l1 meta'); } function makeMatrixGroup1Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = - createMatrixSection().toggleClass('collapsed', - getCollapseState(domain)); - expandosFromNode(domainDiv).domain = domain; - if (hostnames.length > 1) { + let domain = hostnames[0]; + let domainDiv = + createMatrixSection().toggleClass('collapsed', + getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; + if (hostnames.length > 1) { makeMatrixGroup1SectionMetaDomain(domain).appendTo(domainDiv); - } - makeMatrixGroup1SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + } + makeMatrixGroup1SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup1SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup1(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length) { let groupDiv = createMatrixGroup().addClass('g1'); makeMatrixGroup1Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); + .sort(hostnameCompare)) + .appendTo(groupDiv); for (let i=1; i<domains.length; ++i) { - makeMatrixGroup1Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) + makeMatrixGroup1Section(Object.keys(group[domains[i]]) + .sort(hostnameCompare)) .appendTo(groupDiv); } groupDiv.appendTo(matrixList); - } + } } function makeMatrixGroup2SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g2 l1'); + return makeMatrixRowDomain(domain).addClass('g2 l1'); } function makeMatrixGroup2SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g2 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g2 l2'); } function makeMatrixGroup2SectionMetaDomain(domain) { - return makeMatrixMetaRowDomain(domain).addClass('g2 l1 meta'); + return makeMatrixMetaRowDomain(domain).addClass('g2 l1 meta'); } function makeMatrixGroup2Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = - createMatrixSection().toggleClass('collapsed', - getCollapseState(domain)); - expandosFromNode(domainDiv).domain = domain; - if (hostnames.length > 1) { + let domain = hostnames[0]; + let domainDiv = + createMatrixSection().toggleClass('collapsed', + getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; + if (hostnames.length > 1) { makeMatrixGroup2SectionMetaDomain(domain).appendTo(domainDiv); - } - makeMatrixGroup2SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + } + makeMatrixGroup2SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup2SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup2(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length) { let groupDiv = createMatrixGroup().addClass('g2'); makeMatrixGroup2Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); + .sort(hostnameCompare)) + .appendTo(groupDiv); for (let i=1; i<domains.length; ++i) { - makeMatrixGroup2Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) + makeMatrixGroup2Section(Object.keys(group[domains[i]]) + .sort(hostnameCompare)) .appendTo(groupDiv); } groupDiv.appendTo(matrixList); - } + } } function makeMatrixGroup3SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g3 l1'); + return makeMatrixRowDomain(domain).addClass('g3 l1'); } function makeMatrixGroup3SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g3 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g3 l2'); } function makeMatrixGroup3SectionMetaDomain(domain) { - return makeMatrixMetaRowDomain(domain).addClass('g3 l1 meta'); + return makeMatrixMetaRowDomain(domain).addClass('g3 l1 meta'); } function makeMatrixGroup3Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = createMatrixSection().toggleClass('collapsed', - getCollapseState(domain)); - expandosFromNode(domainDiv).domain = domain; - if (hostnames.length > 1) { + let domain = hostnames[0]; + let domainDiv = createMatrixSection().toggleClass('collapsed', + getCollapseState(domain)); + expandosFromNode(domainDiv).domain = domain; + if (hostnames.length > 1) { makeMatrixGroup3SectionMetaDomain(domain).appendTo(domainDiv); - } - makeMatrixGroup3SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + } + makeMatrixGroup3SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup3SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup3(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length) { let groupDiv = createMatrixGroup().addClass('g3'); makeMatrixGroup3Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); + .sort(hostnameCompare)) + .appendTo(groupDiv); for (let i=1; i<domains.length; ++i) { - makeMatrixGroup3Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) + makeMatrixGroup3Section(Object.keys(group[domains[i]]) + .sort(hostnameCompare)) .appendTo(groupDiv); } groupDiv.appendTo(matrixList); - } + } } function makeMatrixGroup4SectionDomain(domain) { - return makeMatrixRowDomain(domain).addClass('g4 l1'); + return makeMatrixRowDomain(domain).addClass('g4 l1'); } function makeMatrixGroup4SectionSubomain(domain, subdomain) { - return makeMatrixRowSubdomain(domain, subdomain).addClass('g4 l2'); + return makeMatrixRowSubdomain(domain, subdomain).addClass('g4 l2'); } function makeMatrixGroup4Section(hostnames) { - let domain = hostnames[0]; - let domainDiv = createMatrixSection(); - expandosFromNode(domainDiv).domain = domain; - makeMatrixGroup4SectionDomain(domain).appendTo(domainDiv); - for (let i=1; i<hostnames.length; ++i) { + let domain = hostnames[0]; + let domainDiv = createMatrixSection(); + expandosFromNode(domainDiv).domain = domain; + makeMatrixGroup4SectionDomain(domain).appendTo(domainDiv); + for (let i=1; i<hostnames.length; ++i) { makeMatrixGroup4SectionSubomain(domain, hostnames[i]) - .appendTo(domainDiv); - } - return domainDiv; + .appendTo(domainDiv); + } + return domainDiv; } function makeMatrixGroup4(group) { - let domains = Object.keys(group).sort(hostnameCompare); - if (domains.length === 0) { + let domains = Object.keys(group).sort(hostnameCompare); + if (domains.length === 0) { return; - } - let groupDiv = createMatrixGroup().addClass('g4'); - createMatrixSection() + } + let groupDiv = createMatrixGroup().addClass('g4'); + createMatrixSection() .addClass('g4Meta') .toggleClass('g4Collapsed', - !!matrixSnapshot.collapseBlacklistedDomains) + !!matrixSnapshot.collapseBlacklistedDomains) .appendTo(groupDiv); - makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g4') + makeMatrixMetaRow(computeMatrixGroupMetaStats(group), 'g4') .appendTo(groupDiv); - makeMatrixGroup4Section(Object.keys(group[domains[0]]) - .sort(hostnameCompare)) + makeMatrixGroup4Section(Object.keys(group[domains[0]]) + .sort(hostnameCompare)) .appendTo(groupDiv); - for (let i=1; i<domains.length; ++i) { + for (let i=1; i<domains.length; ++i) { makeMatrixGroup4Section(Object.keys(group[domains[i]]) - .sort(hostnameCompare)) - .appendTo(groupDiv); - } - groupDiv.appendTo(matrixList); + .sort(hostnameCompare)) + .appendTo(groupDiv); + } + groupDiv.appendTo(matrixList); } let makeMenu = function () { - let groupStats = getGroupStats(); + let groupStats = getGroupStats(); - if (Object.keys(groupStats).length === 0) { - return; - } + if (Object.keys(groupStats).length === 0) { + return; + } - // https://github.com/gorhill/httpswitchboard/issues/31 - if (matrixCellHotspots) { + // https://github.com/gorhill/httpswitchboard/issues/31 + if (matrixCellHotspots) { matrixCellHotspots.detach(); - } + } - renderMatrixHeaderRow(); + renderMatrixHeaderRow(); - startMatrixUpdate(); - makeMatrixGroup0(groupStats[0]); - makeMatrixGroup1(groupStats[1]); - makeMatrixGroup2(groupStats[2]); - makeMatrixGroup3(groupStats[3]); - makeMatrixGroup4(groupStats[4]); - endMatrixUpdate(); + startMatrixUpdate(); + makeMatrixGroup0(groupStats[0]); + makeMatrixGroup1(groupStats[1]); + makeMatrixGroup2(groupStats[2]); + makeMatrixGroup3(groupStats[3]); + makeMatrixGroup4(groupStats[4]); + endMatrixUpdate(); - initScopeCell(); - updateMatrixButtons(); - resizePopup(); + initScopeCell(); + updateMatrixButtons(); + resizePopup(); }; // Do all the stuff that needs to be done before building menu et al. function initMenuEnvironment() { - document.body.style.setProperty('font-size', - getUserSetting('displayTextSize')); - document.body.classList.toggle('colorblind', - getUserSetting('colorBlindFriendly')); - uDom.nodeFromId('version').textContent = - matrixSnapshot.appVersion || ''; - - let prettyNames = matrixHeaderPrettyNames; - let keys = Object.keys(prettyNames); - for (let i=keys.length-1; i>=0; --i) { + document.body.style.setProperty('font-size', + getUserSetting('displayTextSize')); + document.body.classList.toggle('colorblind', + getUserSetting('colorBlindFriendly')); + uDom.nodeFromId('version').textContent = + matrixSnapshot.appVersion || ''; + + let prettyNames = matrixHeaderPrettyNames; + let keys = Object.keys(prettyNames); + for (let i=keys.length-1; i>=0; --i) { let key = keys[i]; let cell = uDom('#matHead .matCell[data-req-type="'+ key +'"]'); let text = vAPI.i18n(key + 'PrettyName'); cell.text(text); prettyNames[key] = text; - } + } - firstPartyLabel = uDom('[data-i18n="matrix1stPartyLabel"]').text(); - blacklistedHostnamesLabel = - uDom('[data-i18n="matrixBlacklistedHostnames"]').text(); + firstPartyLabel = uDom('[data-i18n="matrix1stPartyLabel"]').text(); + blacklistedHostnamesLabel = + uDom('[data-i18n="matrixBlacklistedHostnames"]').text(); } // Create page scopes for the web page function selectGlobalScope() { - if (matrixSnapshot.scope === '*') { - return; - } - matrixSnapshot.scope = '*'; - document.body.classList.add('globalScope'); - matrixSnapshot.tMatrixModifiedTime = undefined; - updateMatrixSnapshot(); - dropDownMenuHide(); + if (matrixSnapshot.scope === '*') { + return; + } + matrixSnapshot.scope = '*'; + document.body.classList.add('globalScope'); + matrixSnapshot.tMatrixModifiedTime = undefined; + updateMatrixSnapshot(); + dropDownMenuHide(); } function selectSpecificScope(ev) { - let newScope = ev.target.getAttribute('data-scope'); - if (!newScope || matrixSnapshot.scope === newScope) { - return; - } - document.body.classList.remove('globalScope'); - matrixSnapshot.scope = newScope; - matrixSnapshot.tMatrixModifiedTime = undefined; - updateMatrixSnapshot(); - dropDownMenuHide(); + let newScope = ev.target.getAttribute('data-scope'); + if (!newScope || matrixSnapshot.scope === newScope) { + return; + } + document.body.classList.remove('globalScope'); + matrixSnapshot.scope = newScope; + matrixSnapshot.tMatrixModifiedTime = undefined; + updateMatrixSnapshot(); + dropDownMenuHide(); } function initScopeCell() { - // It's possible there is no page URL at this point: some pages cannot - // be filtered by ηMatrix. - if (matrixSnapshot.url === '') { - return; - } - let specificScope = uDom.nodeFromId('specificScope'); - - while (specificScope.firstChild !== null) { + // It's possible there is no page URL at this point: some pages cannot + // be filtered by ηMatrix. + if (matrixSnapshot.url === '') { + return; + } + let specificScope = uDom.nodeFromId('specificScope'); + + while (specificScope.firstChild !== null) { specificScope.removeChild(specificScope.firstChild); - } + } - // Fill in the scope menu entries - let pos = matrixSnapshot.domain.indexOf('.'); - let tld, labels; - if (pos === -1) { + // Fill in the scope menu entries + let pos = matrixSnapshot.domain.indexOf('.'); + let tld, labels; + if (pos === -1) { tld = ''; labels = matrixSnapshot.hostname; - } else { + } else { tld = matrixSnapshot.domain.slice(pos + 1); labels = matrixSnapshot.hostname.slice(0, -tld.length); - } - let beg = 0; - let span, label; - while (beg < labels.length) { + } + let beg = 0; + let span, label; + while (beg < labels.length) { pos = labels.indexOf('.', beg); if (pos === -1) { - pos = labels.length; + pos = labels.length; } else { - pos += 1; + pos += 1; } label = document.createElement('span'); label.appendChild(document - .createTextNode(Punycode - .toUnicode(labels.slice(beg, - pos)))); + .createTextNode(Punycode + .toUnicode(labels.slice(beg, + pos)))); span = document.createElement('span'); span.setAttribute('data-scope', labels.slice(beg) + tld); span.appendChild(label); specificScope.appendChild(span); beg = pos; - } - if (tld !== '') { + } + if (tld !== '') { label = document.createElement('span'); label.appendChild(document.createTextNode(Punycode.toUnicode(tld))); span = document.createElement('span'); span.setAttribute('data-scope', tld); span.appendChild(label); specificScope.appendChild(span); - } - updateScopeCell(); + } + updateScopeCell(); } function updateScopeCell() { - let specificScope = uDom.nodeFromId('specificScope'); + let specificScope = uDom.nodeFromId('specificScope'); let isGlobal = matrixSnapshot.scope === '*'; - document.body.classList.toggle('globalScope', isGlobal); - specificScope.classList.toggle('on', !isGlobal); - uDom.nodeFromId('globalScope').classList.toggle('on', isGlobal); + document.body.classList.toggle('globalScope', isGlobal); + specificScope.classList.toggle('on', !isGlobal); + uDom.nodeFromId('globalScope').classList.toggle('on', isGlobal); - for (let node of specificScope.children) { + for (let node of specificScope.children) { node.classList.toggle('on', - !isGlobal - && matrixSnapshot - .scope - .endsWith(node.getAttribute('data-scope'))); - } + !isGlobal + && matrixSnapshot + .scope + .endsWith(node.getAttribute('data-scope'))); + } } function updateMatrixSwitches() { - let count = 0; + let count = 0; let enabled; let switches = matrixSnapshot.tSwitches; - for (let switchName in switches) { + for (let switchName in switches) { if (switches.hasOwnProperty(switchName) === false) { - continue; - } + continue; + } enabled = switches[switchName]; if (enabled && switchName !== 'matrix-off') { - count += 1; + count += 1; } uDom('#mtxSwitch_' + switchName).toggleClass('switchTrue', enabled); - } - uDom.nodeFromId('mtxSwitch_https-strict') - .classList - .toggle('relevant', matrixSnapshot.hasMixedContent); - uDom.nodeFromId('mtxSwitch_no-workers') - .classList - .toggle('relevant', matrixSnapshot.hasWebWorkers); - uDom.nodeFromId('mtxSwitch_referrer-spoof') - .classList.toggle('relevant', matrixSnapshot.has3pReferrer); - uDom.nodeFromId('mtxSwitch_noscript-spoof') - .classList - .toggle('relevant', matrixSnapshot.hasNoscriptTags); - uDom.nodeFromSelector('#buttonMtxSwitches span.badge').textContent = + } + uDom.nodeFromId('mtxSwitch_https-strict') + .classList + .toggle('relevant', matrixSnapshot.hasMixedContent); + uDom.nodeFromId('mtxSwitch_no-workers') + .classList + .toggle('relevant', matrixSnapshot.hasWebWorkers); + uDom.nodeFromId('mtxSwitch_referrer-spoof') + .classList.toggle('relevant', matrixSnapshot.has3pReferrer); + uDom.nodeFromId('mtxSwitch_noscript-spoof') + .classList + .toggle('relevant', matrixSnapshot.hasNoscriptTags); + uDom.nodeFromSelector('#buttonMtxSwitches span.badge').textContent = count.toLocaleString(); - uDom.nodeFromSelector('#mtxSwitch_matrix-off span.badge').textContent = + uDom.nodeFromSelector('#mtxSwitch_matrix-off span.badge').textContent = matrixSnapshot.blockedCount.toLocaleString(); - document.body.classList.toggle('powerOff', switches['matrix-off']); + document.body.classList.toggle('powerOff', switches['matrix-off']); } function toggleMatrixSwitch(ev) { - if (ev.target.localName === 'a') { - return; - } - - let elem = ev.currentTarget; - let pos = elem.id.indexOf('_'); - if (pos === -1) { - return; - } - - let switchName = elem.id.slice(pos + 1); - let request = { + if (ev.target.localName === 'a') { + return; + } + + let elem = ev.currentTarget; + let pos = elem.id.indexOf('_'); + if (pos === -1) { + return; + } + + let switchName = elem.id.slice(pos + 1); + let request = { what: 'toggleMatrixSwitch', switchName: switchName, srcHostname: matrixSnapshot.scope - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } function updatePersistButton() { - let diffCount = matrixSnapshot.diff.length; - let button = uDom('#buttonPersist'); + let diffCount = matrixSnapshot.diff.length; + let button = uDom('#buttonPersist'); - button.contents() + button.contents() .filter(function () { - return this.nodeType===3; - }) - .first() + return this.nodeType===3; + }) + .first() .text(diffCount > 0 ? '\uf13e' : '\uf023'); - button.descendants('span.badge').text(diffCount > 0 ? diffCount : ''); + button.descendants('span.badge').text(diffCount > 0 ? diffCount : ''); - let disabled = diffCount === 0; + let disabled = diffCount === 0; - button.toggleClass('disabled', disabled); - uDom('#buttonRevertScope').toggleClass('disabled', disabled); + button.toggleClass('disabled', disabled); + uDom('#buttonRevertScope').toggleClass('disabled', disabled); } function persistMatrix() { - let request = { + let request = { what: 'applyDiffToPermanentMatrix', diff: matrixSnapshot.diff - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } // rhill 2014-03-12: revert completely ALL changes related to the // current page, including scopes. function revertMatrix() { - let request = { + let request = { what: 'applyDiffToTemporaryMatrix', diff: matrixSnapshot.diff - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); } // Buttons which are affected by any changes in the matrix function updateMatrixButtons() { - updateScopeCell(); - updateMatrixSwitches(); - updatePersistButton(); + updateScopeCell(); + updateMatrixSwitches(); + updatePersistButton(); } function revertAll() { - let request = { + let request = { what: 'revertTemporaryMatrix' - }; - vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); - dropDownMenuHide(); + }; + vAPI.messaging.send('popup.js', request, updateMatrixSnapshot); + dropDownMenuHide(); } function buttonReloadHandler(ev) { - vAPI.messaging.send('popup.js', { + vAPI.messaging.send('popup.js', { what: 'forceReloadTab', tabId: matrixSnapshot.tabId, bypassCache: ev.ctrlKey || ev.metaKey || ev.shiftKey - }); + }); } function mouseenterMatrixCellHandler(ev) { - matrixCellHotspots.appendTo(ev.target); + matrixCellHotspots.appendTo(ev.target); } function mouseleaveMatrixCellHandler() { - matrixCellHotspots.detach(); + matrixCellHotspots.detach(); } function gotoExtensionURL(ev) { - let url = uDom(ev.currentTarget).attr('data-extension-url'); - if (url) { + let url = uDom(ev.currentTarget).attr('data-extension-url'); + if (url) { vAPI.messaging.send('popup.js', { - what: 'gotoExtensionURL', - url: url, - shiftKey: ev.shiftKey + what: 'gotoExtensionURL', + url: url, + shiftKey: ev.shiftKey }); - } - dropDownMenuHide(); - vAPI.closePopup(); + } + dropDownMenuHide(); + vAPI.closePopup(); } function dropDownMenuShow(ev) { - let button = ev.target; - let menuOverlay = document.getElementById(button.getAttribute('data-dropdown-menu')); - let butnRect = button.getBoundingClientRect(); - let viewRect = document.body.getBoundingClientRect(); - let butnNormalLeft = butnRect.left / (viewRect.width - butnRect.width); - menuOverlay.classList.add('show'); - let menu = menuOverlay.querySelector('.dropdown-menu'); - let menuRect = menu.getBoundingClientRect(); - let menuLeft = butnNormalLeft * (viewRect.width - menuRect.width); - menu.style.left = menuLeft.toFixed(0) + 'px'; - menu.style.top = butnRect.bottom + 'px'; + let button = ev.target; + let menuOverlay = document.getElementById(button.getAttribute('data-dropdown-menu')); + let butnRect = button.getBoundingClientRect(); + let viewRect = document.body.getBoundingClientRect(); + let butnNormalLeft = butnRect.left / (viewRect.width - butnRect.width); + menuOverlay.classList.add('show'); + let menu = menuOverlay.querySelector('.dropdown-menu'); + let menuRect = menu.getBoundingClientRect(); + let menuLeft = butnNormalLeft * (viewRect.width - menuRect.width); + menu.style.left = menuLeft.toFixed(0) + 'px'; + menu.style.top = butnRect.bottom + 'px'; } function dropDownMenuHide() { - uDom('.dropdown-menu-capture').removeClass('show'); + uDom('.dropdown-menu-capture').removeClass('show'); } let onMatrixSnapshotReady = function (response) { - if (response === 'ENOTFOUND') { + if (response === 'ENOTFOUND') { uDom.nodeFromId('noTabFound').textContent = - vAPI.i18n('matrixNoTabFound'); + vAPI.i18n('matrixNoTabFound'); document.body.classList.add('noTabFound'); return; - } + } - // Now that tabId and pageURL are set, we can build our menu - initMenuEnvironment(); - makeMenu(); + // Now that tabId and pageURL are set, we can build our menu + initMenuEnvironment(); + makeMenu(); - // After popup menu is built, check whether there is a non-empty matrix - if (matrixSnapshot.url === '') { + // After popup menu is built, check whether there is a non-empty matrix + if (matrixSnapshot.url === '') { uDom('#matHead').remove(); uDom('#toolbarContainer').remove(); // https://github.com/gorhill/httpswitchboard/issues/191 uDom('#noNetTrafficPrompt').text(vAPI.i18n('matrixNoNetTrafficPrompt')); uDom('#noNetTrafficPrompt').css('display', ''); - } - - // Create a hash to find out whether the reload button needs to be - // highlighted. - // TODO: - // ηMatrix: not sure what the purpose of highlighting is... - // Maybe telling the user that the page needs refreshing? But - // that's hardly useful (and by now people have gotten used to - // the lack of such a feature.) - // Not really going to do it, but let's leave the comment. + } + + // Create a hash to find out whether the reload button needs to be + // highlighted. + // TODO: + // ηMatrix: not sure what the purpose of highlighting is... + // Maybe telling the user that the page needs refreshing? But + // that's hardly useful (and by now people have gotten used to + // the lack of such a feature.) + // Not really going to do it, but let's leave the comment. }; let matrixSnapshotPoller = (function () { - let timer = null; + let timer = null; - let preprocessMatrixSnapshot = function (snapshot) { + let preprocessMatrixSnapshot = function (snapshot) { if (Array.isArray(snapshot.headerIndices)) { - snapshot.headerIndices = new Map(snapshot.headerIndices); + snapshot.headerIndices = new Map(snapshot.headerIndices); } return snapshot; - }; + }; - let processPollResult = function (response) { + let processPollResult = function (response) { if (typeof response !== 'object') { - return; + return; } if (response.mtxContentModified === false - && response.mtxCountModified === false - && response.pMatrixModified === false - && response.tMatrixModified === false) { - return; + && response.mtxCountModified === false + && response.pMatrixModified === false + && response.tMatrixModified === false) { + return; } matrixSnapshot = preprocessMatrixSnapshot(response); if (response.mtxContentModified) { - makeMenu(); - return; + makeMenu(); + return; } if (response.mtxCountModified) { - updateMatrixCounts(); + updateMatrixCounts(); } if (response.pMatrixModified - || response.tMatrixModified - || response.scopeModified) { - updateMatrixColors(); - updateMatrixBehavior(); - updateMatrixButtons(); + || response.tMatrixModified + || response.scopeModified) { + updateMatrixColors(); + updateMatrixBehavior(); + updateMatrixButtons(); } - }; + }; - let onPolled = function (response) { + let onPolled = function (response) { processPollResult(response); pollAsync(); - }; + }; - let pollNow = function () { + let pollNow = function () { unpollAsync(); vAPI.messaging.send('popup.js', { - what: 'matrixSnapshot', - tabId: matrixSnapshot.tabId, - scope: matrixSnapshot.scope, - mtxContentModifiedTime: matrixSnapshot.mtxContentModifiedTime, - mtxCountModifiedTime: matrixSnapshot.mtxCountModifiedTime, - mtxDiffCount: matrixSnapshot.diff.length, - pMatrixModifiedTime: matrixSnapshot.pMatrixModifiedTime, - tMatrixModifiedTime: matrixSnapshot.tMatrixModifiedTime, + what: 'matrixSnapshot', + tabId: matrixSnapshot.tabId, + scope: matrixSnapshot.scope, + mtxContentModifiedTime: matrixSnapshot.mtxContentModifiedTime, + mtxCountModifiedTime: matrixSnapshot.mtxCountModifiedTime, + mtxDiffCount: matrixSnapshot.diff.length, + pMatrixModifiedTime: matrixSnapshot.pMatrixModifiedTime, + tMatrixModifiedTime: matrixSnapshot.tMatrixModifiedTime, }, onPolled); - }; + }; - let poll = function () { + let poll = function () { timer = null; pollNow(); - }; + }; - let pollAsync = function () { + let pollAsync = function () { if (timer !== null) { - return; + return; } if (document.defaultView === null) { - return; + return; } timer = vAPI.setTimeout(poll, 1414); - }; + }; - let unpollAsync = function () { + let unpollAsync = function () { if (timer !== null) { - clearTimeout(timer); - timer = null; + clearTimeout(timer); + timer = null; } - }; + }; - (function () { + (function () { let tabId = matrixSnapshot.tabId; // If no tab id yet, see if there is one specified in our URL if (tabId === undefined) { - let matches = window - .location - .search - .match(/(?:\?|&)tabId=([^&]+)/); + let matches = window + .location + .search + .match(/(?:\?|&)tabId=([^&]+)/); - if (matches !== null) { + if (matches !== null) { tabId = matches[1]; // No need for logger button when embedded in logger uDom('[data-extension-url="logger-ui.html"]').remove(); - } + } } let snapshotFetched = function (response) { - if (typeof response === 'object') { + if (typeof response === 'object') { matrixSnapshot = preprocessMatrixSnapshot(response); - } - onMatrixSnapshotReady(response); - pollAsync(); + } + onMatrixSnapshotReady(response); + pollAsync(); }; vAPI.messaging.send('popup.js', { - what: 'matrixSnapshot', - tabId: tabId + what: 'matrixSnapshot', + tabId: tabId }, snapshotFetched); - })(); + })(); - return { + return { pollNow: pollNow - }; + }; })(); // Below is UI stuff which is not key to make the menu, so this can @@ -1536,8 +1536,8 @@ matrixCellHotspots = uDom('#cellHotspots').detach(); uDom('body') - .on('mouseenter', '.matCell', mouseenterMatrixCellHandler) - .on('mouseleave', '.matCell', mouseleaveMatrixCellHandler); + .on('mouseenter', '.matCell', mouseenterMatrixCellHandler) + .on('mouseleave', '.matCell', mouseleaveMatrixCellHandler); uDom('#specificScope').on('click', selectSpecificScope); uDom('#globalScope').on('click', selectGlobalScope); @@ -1553,9 +1553,9 @@ uDom('body').on('click', '.dropdown-menu-capture', dropDownMenuHide); uDom('#matList').on('click', '.g4Meta', function (ev) { - matrixSnapshot.collapseBlacklistedDomains = + matrixSnapshot.collapseBlacklistedDomains = ev.target.classList.toggle('g4Collapsed'); - setUserSetting('popupCollapseBlacklistedDomains', - matrixSnapshot.collapseBlacklistedDomains); + setUserSetting('popupCollapseBlacklistedDomains', + matrixSnapshot.collapseBlacklistedDomains); }); })(); |