Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved C2P Script Injection #528

Merged
merged 11 commits into from Apr 28, 2020

fixing bugs in c2p social icons. Pass entire queue to content script …

…after injection
  • Loading branch information
christophertino committed Apr 22, 2020
commit e688490ae693f33cf96952102b4b10b1d249a2cf
@@ -26,7 +26,6 @@ const { onMessage } = chrome.runtime;
* @var {Object} initialized with an object with exported init as its property
*/
const Click2PlayContentScript = (function(win, doc) {
const C2P_DATA = {};
/**
* Create element for the specified html tag
* @memberof Click2PlayContentScript
@@ -52,10 +51,9 @@ const Click2PlayContentScript = (function(win, doc) {
}
};
/**
* Helper called by applyC2P
* This function creates a fragment of DOM used for replacement
* of a social tracker.
* It also sets listeners to mouse 'click' events.
* Helper function called by applyC2P(). This function creates a
* DOM fragment used to replace a social tracker. It also sets
* listeners for mouse 'click' events.
* @memberof Click2PlayContentScript
* @package
*
@@ -66,13 +64,10 @@ const Click2PlayContentScript = (function(win, doc) {
const buildC2P = function(c2pFrame, c2pAppDef, html) {
c2pFrame.addEventListener('load', () => {
const idoc = c2pFrame.contentDocument;

idoc.documentElement.innerHTML = html;
const image = idoc.getElementById('ghostery-button');

if (c2pAppDef.button) {
c2pFrame.style.width = `${image.width}px`;
c2pFrame.style.height = `${image.height}px`;
c2pFrame.style.width = '30px';
c2pFrame.style.height = '19px';
c2pFrame.style.border = '0px';
} else {
c2pFrame.style.width = '100%';
@@ -127,31 +122,30 @@ const Click2PlayContentScript = (function(win, doc) {
const els = doc.querySelectorAll(c2pAppDef.ele);
for (let i = 0, num_els = els.length; i < num_els; i++) {
const el = els[i];

const c2pFrame = createEl('iframe');

buildC2P(c2pFrame, c2pAppDef, html[idx]);
c2pFrame.style.display = 'inline-block';

if ((c2pAppDef.attach && c2pAppDef.attach === 'parentNode') ||
(el.nodeName === 'IFRAME')) {
// Attach C2P frame inside the parentNode
if ((c2pAppDef.attach && c2pAppDef.attach === 'parentNode') || (el.nodeName === 'IFRAME')) {
if (el.parentNode && el.parentNode.nodeName !== 'BODY' && el.parentNode.nodeName !== 'HEAD') {
el.parentNode.replaceChild(c2pFrame, el);
return;
}
}

// Replace existing node with C2P content
el.textContent = '';

el.style.display = 'inline-block';
appendChild(el, c2pFrame);
}
});
};
/**
* Initialize Click2PlayContentScript.
* This function sets listener for 'c2p' message coming from background with
* tracker-related data. It also sets listener for windows 'load' event.
* Called by exported init function.
* Initialize Click2PlayContentScript. This function sets a listener for 'c2p' messages
* with tracker-related data. This script is injected on document_idle after DOM complete.
* Called by exported init() function.
* @memberof Click2PlayContentScript
* @package
*/
@@ -161,34 +155,28 @@ const Click2PlayContentScript = (function(win, doc) {
return false;
}

const { name, message } = request;
const { name, message } = request;
log('click_to_play.js received message', name);

if (name === 'c2p') {
if (message) {
// queue Click-to-Play data so that we process multiple Twitter buttons at once, for example
C2P_DATA[message.app_id] = [message.app_id, message.data, message.html];

if (doc.readyState === 'complete') {
// Dequeue C2P data stored while the script injection was taking place
if (Array.isArray(message)) {
let m = message.shift();
while (m !== undefined) {
applyC2P(m.app_id, m.data, m.html);
m = message.shift();
}
} else {
// Single C2P message
applyC2P(message.app_id, message.data, message.html);
}
}
}

sendResponse();
return true;
return false;
});

window.addEventListener('load', () => {
for (const app_id in C2P_DATA) {
if (C2P_DATA.hasOwnProperty(app_id)) {
if (C2P_DATA[app_id].length >= 3) {
applyC2P(C2P_DATA[app_id][0], C2P_DATA[app_id][1], C2P_DATA[app_id][2]);
}
}
}
// TODO clear C2P_DATA to free memory
}, { capture: false, passive: true });
};

// Public API
@@ -768,7 +768,7 @@ const NotificationsContentScript = (function(win, doc) {
exportFile(message);
}

// trigger a response callback to src/background so that we can handler errors properly
// trigger a response callback to src/background so that we can handle errors properly
sendResponse();
return true;
});
@@ -103,17 +103,10 @@ export function buildC2P(details, app_id) {
switch (tab.c2pStatus) {
case 'none':
tab.c2pStatus = 'loading';
injectScript(tab_id, 'dist/click_to_play.js', '', 'document_end').then(() => {
// Dequeue C2P data stored while the script injection was taking place
let msg = tab.c2pQueue.shift();
while (msg !== undefined) {
sendMessage(tab_id, 'c2p', {
app_id: msg.app_id,
data: msg.c2pApp,
html: msg.c2pHtml
});
msg = tab.c2pQueue.shift();
}
// Scripts injected at document_idle are guaranteed to run after the DOM is complete
injectScript(tab_id, 'dist/click_to_play.js', '', 'document_idle').then(() => {
// Send the entire queue to the content script to reduce message passing
sendMessage(tab_id, 'c2p', tab.c2pQueue);
tab.c2pStatus = 'done';
}).catch((err) => {
log('buildC2P error', err);
@@ -123,8 +116,8 @@ export function buildC2P(details, app_id) {
// Push C2P data to a holding queue until click_to_play.js has finished loading on the page
tab.c2pQueue.push({
app_id,
c2pApp,
c2pHtml
data: c2pApp,
html: c2pHtml
});
break;
case 'done':
@@ -143,9 +136,9 @@ export function buildC2P(details, app_id) {
* Build blocked redirect data global structure Inject Page-Level Click2Play on Redirect.
* @memberOf BackgroundUtils
*
* @param {number} requestId request id
* @param {number} requestId request id
* @param {Object} redirectUrls original url and redirect url as properties
* @param {number} app_id tracker id
* @param {number} app_id tracker id
*
* @return {string} url of the internal template of the blocked redirect page
*/
@@ -540,7 +540,7 @@ export function fetchLocalJSONResource(url) {
}

/**
* Inject content scripts and CSS into a given tabID.
* Inject content scripts and CSS into a given tabID (top-level frame only).
* Note: Chrome 61 blocks content scripts on the new tab page (_/chrome/newtab). Be
* sure to check the current URL before calling this function, otherwise Chrome will throw
* a permission error
ProTip! Use n and p to navigate between commits in a pull request.