Skip to content

Commit

Permalink
Make CWS button click area encompass whole button
Browse files Browse the repository at this point in the history
Due to updates on CWS, the click area was not the whole visual button. The edges after the label were not triggering it. I changed the technique from global event listener, this one is much cleaner.
  • Loading branch information
Noitidart committed May 27, 2019
1 parent 0669754 commit 6e6f0c2
Showing 1 changed file with 103 additions and 51 deletions.
154 changes: 103 additions & 51 deletions src/webext/content_scripts/cws/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@

import 'cmn/lib/extension-polyfill'

window.addEventListener('click', genericClick, true);
function uninit() {
removeStyleSheet();
removeInstallClickHandlers(document.body);
unwatchAddingInstallHandlers();
}

function init() {
addStyleSheet();
addInstallClickHandlers(document.body);
watchForAddingInstallHandlers();
}

init();

(function() {
const style = document.createElement('style');
style.setAttribute('id', 'foxified-style')
style.textContent = `
function addStyleSheet() {
const styleSheet = document.createElement('style');
styleSheet.setAttribute('id', 'foxified-style')
styleSheet.textContent = `
div[role=button][aria-label*="CHROME"],
div[role=button][aria-label*="Chrome"]
{
Expand Down Expand Up @@ -41,56 +53,96 @@ window.addEventListener('click', genericClick, true);
}
`;

document.documentElement.insertBefore(style, document.documentElement.firstChild);
})()
document.documentElement.insertBefore(styleSheet, document.documentElement.firstChild);
}

function uninit() {
var style = document.getElementById('foxified-style');
if (style) style.parentNode.removeChild(style);
function removeStyleSheet() {
const styleSheet = document.getElementById('foxified-style');
if (styleSheet) styleSheet.parentNode.removeChild(styleSheet);
}

/**
* If return is truthy, the return value is returned.
*
*/
function parentNodeUntil(node, maxDepth, predicate) {
let curNode = node;
let rez;
let depth = 0;
while (!rez && depth++ < maxDepth) {
rez = predicate(curNode);
if (!rez) curNode = curNode.parentNode;
}
return rez;
}

function handleInstall(e) {
e.preventDefault();
e.stopPropagation();

// start figure out id
// Thanks to @Rob--W the id is accurately obtained: "It is the first 32 characters of the public key's sha256 hash, with the 0-9a-f replaced with a-p"
const extidPatt = /[^a-p]([a-p]{32})[^a-p]/i;
const extid = parentNodeUntil(e.target, 100, node => {
if (node.nodeType === Node.ELEMENT_NODE) {
const [, extid] = extidPatt.exec(node.innerHTML) || [];
console.log('extid:', extid);
return extid;
}
});

if (!extid) alert('Chrome Store Foxified enecountered an error. Failed to figure out extension ID.')
else extension.runtime.sendMessage({
action: 'request-add',
kind: 'cws',
extid
});
}

function addInstallClickHandlers(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
const buttons = [
...node.querySelectorAll('div[role=button][aria-label*="Chrome"]'),
...node.querySelectorAll('div[role=button][aria-label*="CHROME"]')
];

window.removeEventListener('click', genericClick, true);
for (const button of buttons) {
button.addEventListener('click', handleInstall, true);
}
}
}

function genericClick(e) {
const target = e.target;
console.log('clicked, target:', target.innerHTML);
if (target) {
if (e.button !== 0) return;

const isTestButton = target.classList.contains('webstore-test-button-label');
const isRoleButton = target.getAttribute('role') === 'button';
let hasTestButton;
try {
hasTestButton = target.querySelector('.webstore-test-button-label');
} catch(ignore) {} // eslint-disable-line no-empty
// console.log('isTestButton:', isTestButton, 'isRoleButton:', isRoleButton, 'hasTestButton:', hasTestButton);

if (isTestButton || (isRoleButton && hasTestButton)) { // eslint-disable-line no-extra-parens
const ariaLabel = isRoleButton ? target.getAttribute('aria-label') : undefined;
const buttonLabel = isTestButton ? target.textContent.trim() : undefined;

console.log('ariaLabel:', ariaLabel, 'btnText:', buttonLabel);
const patt = /(?:CHROM|Chrom)/;
if (patt.test(ariaLabel) || patt.test(buttonLabel)) {
e.stopPropagation();
e.preventDefault();

let extid;

// start figure out id
const extidPatt = /[^a-p]([a-p]{32})[^a-p]/i; // Thanks to @Rob--W the id is accurately obtained: "It is the first 32 characters of the public key's sha256 hash, with the 0-9a-f replaced with a-p"
let searchTarget = target;
let i = 0;
while (i < 100) {
searchTarget = searchTarget.parentNode;
if (!searchTarget) break;
([, extid] = extidPatt.exec(searchTarget.innerHTML) || []); // eslint-disable-line no-extra-parens
if (extid) break;
function removeInstallClickHandlers(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
const buttons = [
...node.querySelectorAll('div[role=button][aria-label*="Chrome"]'),
...node.querySelectorAll('div[role=button][aria-label*="CHROME"]')
];

for (const button of buttons) {
button.removeEventListener('click', handleInstall, true);
}
}
}

let gObserver;
function watchForAddingInstallHandlers() {
gObserver = new MutationObserver(mutations => {
for (const mutation of mutations) {
if (mutation.type === 'childList') {
for (const node of mutation.addedNodes) {
addInstallClickHandlers(node);
}
}
}
});

gObserver.observe(document.body, {
childList: true,
subtree: true
});
}

if (!extid) alert('Chrome Store Foxified enecountered an error. Failed to figure out extension ID.')
else extension.runtime.sendMessage({ action:'request-add', kind:'cws', extid });
}
}
}
function unwatchAddingInstallHandlers() {
gObserver.disconnect();
}

0 comments on commit 6e6f0c2

Please sign in to comment.