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
@@ -19,19 +19,22 @@ yarn-error.log
tools/i18n_results
tools/leet/*.json

# Cliqz
## Cliqz
cliqz/

# Tools
## Tools
tools/amo/*.zip

## JSDoc
docs/
jsdocs/
out/

#OSX
## Jest
coverage/

## OSX
.DS_Store

#Other Files
## Other Files
bug-list.md
@@ -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%';
@@ -125,33 +120,31 @@ const Click2PlayContentScript = (function(win, doc) {
const applyC2P = function(app_id, c2p_app, html) {
c2p_app.forEach((c2pAppDef, idx) => {
const els = doc.querySelectorAll(c2pAppDef.ele);
for (let i = 0, num_els = els.length; i < num_els; i++) {
for (let i = 0; i < els.length; 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;
}
} else {
// Replace existing node with C2P content
el.textContent = '';
el.style.display = 'inline-block';
appendChild(el, c2pFrame);
}

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 +154,24 @@ 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') {
applyC2P(message.app_id, message.data, message.html);
// Dequeue C2P data stored while the script injection was taking place
for (const app_id in message) {
if (message.hasOwnProperty(app_id)) {
applyC2P(app_id, message[app_id].data, message[app_id].html);
delete message[app_id];
}
}
}
}

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;
});
@@ -167,10 +167,10 @@
}

.cliqz-tracker-trust > g > path:nth-child(1) {
stroke: #00AEF0;
stroke: #d8d8d8;
}
.cliqz-tracker-trust > g > path:nth-child(2) {
fill: #00AEF0;
fill: #f7f7f7;
}
.cliqz-tracker-scrub > g > .border {
fill: #FFF;
@@ -694,7 +694,7 @@ class EventHandlers {
};
}
} else if (fromRedirect) {
const url = buildRedirectC2P(requestId, globals.REDIRECT_MAP.get(requestId), appId);
const url = buildRedirectC2P(globals.REDIRECT_MAP.get(requestId), appId);
setTimeout(() => {
chrome.tabs.update(details.tabId, { url });
}, 0);
@@ -878,7 +878,7 @@ class EventHandlers {
*
*/
_resetNotifications() {
globals.C2P_LOADED = globals.NOTIFICATIONS_LOADED = false; // eslint-disable-line no-multi-assign
globals.NOTIFICATIONS_LOADED = false;
}
}

@@ -41,7 +41,6 @@ class Globals {
this.REQUIRE_LEGACY_OPT_IN = false;
this.HOTFIX = false;
this.LET_REDIRECTS_THROUGH = false;
this.C2P_LOADED = false;
this.NOTIFICATIONS_LOADED = false;
this.upgrade_alert_shown = false;

@@ -2,6 +2,8 @@
* TabInfo Class
*
* this._tabInfo[tab_id]: {
* c2pStatus {string} current status of the click_to_play.js script injection on the tab (none|loading|done)
* c2pQueue {Object} queue of c2p messages collected when c2pStatus is 'none' or 'loading', organized as a HashSet by app_id
* domain: {string} the general domain name plus suffix (no sub-domains)
* hash: {string} hash values appended to the url
* host: {string} the domain name plus suffix and sub-domains
@@ -46,7 +48,7 @@ class TabInfo {

/**
* Create a new _tabInfo object
* @param {number} tab_id tab id
* @param {number} tab_id tab id
* @param {string} tab_url tab url
*/
create(tab_id, tab_url) {
@@ -68,6 +70,8 @@ class TabInfo {
unblocked: {},
},
insecureRedirects: [],
c2pStatus: 'none',
c2pQueue: {},
};

this._tabInfo[tab_id] = info;
@@ -76,12 +80,12 @@ class TabInfo {

/**
* Getter method
* @param {number} tab_id tab id
* @param {number} tab_id tab id
* @param {string} property property name
* @return {Object} _tabInfo data
*/
// TODO consider improving handling of what if we mistype the property name.
// always returning object where property might sometimes have returned false could result in subtle bugs.
// TODO consider improving handling of what happens if we mistype the property name. Always
// returning an object where property would otherwise have returned false could result in subtle bugs.
getTabInfo(tab_id, property) {
if (this._tabInfo.hasOwnProperty(tab_id)) {
if (property) {
@@ -94,8 +98,8 @@ class TabInfo {

/**
* Getter method for tab parameters which we want to persist during the session.
* @param {number} tab_id tab id
* @param {string} property persitant property name
* @param {number} tab_id tab id
* @param {string} property persistent property name
* @return {Object} persistent data for this tab
*/
getTabInfoPersist(tab_id, property) {
@@ -167,7 +171,7 @@ class TabInfo {
*
* @private
*
* @param {number} tab_id tab id
* @param {number} tab_id tab id
* @param {string} tab_url tab url
*/
_updateUrl(tab_id, tab_url) {
ProTip! Use n and p to navigate between commits in a pull request.