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

[Issue #6] add vendor list #27

Merged
merged 8 commits into from
Nov 14, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions src/js/vendorUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* global chrome */
/* global browser */
/* eslint-disable guard-for-in */
let api;
if (chrome === undefined) {
api = browser;
} else {
api = chrome;
}

export function findVendor(id, vendorList) {
return vendorList.vendors[id];
}

export function showVendors(vendorList, allowedVendorIds) {
const vendorsListElement = document.getElementById('vendors_list');
allowedVendorIds.forEach((id) => {
const vendor = findVendor(id, vendorList);
let vendorName;
if (vendor === undefined) {
vendorName = `{Incorrect vendor, ID ${id}}`;
} else {
vendorName = vendor.name;
const listItem = document.createElement('li');
const vendorLink = document.createElement('a');
vendorLink.href = vendor.policyUrl;
vendorLink.target = '_blank';
vendorLink.innerText = vendorName;

if (vendor.purposes.length === 0) {
vendorName += ' [*]';
}
listItem.appendChild(vendorLink);
vendorsListElement.appendChild(listItem);
}
});
}

export function fetchVendorList(vendorListVersion, allowedVendors) {
const req = new Request(`https://vendor-list.consensu.org/v${vendorListVersion}/vendor-list.json`, {
method: 'GET',
headers: { Accept: 'application/json' },
redirect: 'follow',
referrer: 'client',
});

fetch(req).then((response) => response.json()).then((data) => {
const a = {};
a[`vendorList_${vendorListVersion}`] = data;
api.storage.local.set(a);
showVendors(data, allowedVendors);
}).catch((error) => {
console.log('Error fetching vendor list: ', error);
// TODO: surface generic error message in pop-up
});
}
112 changes: 35 additions & 77 deletions src/popup/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import '../button/38.png';
import './ucookie.css';
import { TCString } from '@iabtcf/core';
import cmpListFull from './IAB_CMP_list_full';
import { fetchVendorList, showVendors } from '../js/vendorUtils';

const vendorListVersion = 2;
let api;
if (chrome === undefined) {
api = browser;
Expand Down Expand Up @@ -74,6 +76,7 @@ function showCmp(cmpId) {
document.getElementById('cmp').textContent = `Unknown CMP ID ${cmpId}. Search for it on the cmp-list: `;
const a = document.createElement('a');
a.href = 'https://iabeurope.eu/cmp-list/';
a.target = '_blank';
a.appendChild(document.createTextNode('https://iabeurope.eu/cmp-list/'));
document.getElementById('cmp').appendChild(a);
}
Expand Down Expand Up @@ -124,11 +127,42 @@ function showTimestamps(createdAt, lastUpdated, lastFetched) {
document.getElementById('last_fetched').textContent = formatIntlDate(lastFetched);
}

function loadVendors(vendorConsents) {
const allowedVendors = vendorConsents.set_;
const vendorListName = `vendorList_${vendorListVersion}`;
api.storage.local.get([`vendorList_${vendorListVersion}`], (result) => {
if (result[vendorListName] === undefined) {
// vendorList is not in localstorage, load it from IAB's website
document.getElementById('vendors_container').appendChild(document.createTextNode('Loading vendor list...'));
fetchVendorList(vendorListVersion, allowedVendors);
} else {
// vendorList is in locals storage
showVendors(result[vendorListName], allowedVendors);
}
});
}

function handleTCData(data, timestampTcDataLoaded) {
showCmp(data.cmpId_);
showNumVendors(data.vendorConsents);
showPurposes(data.purposeConsents);
showTimestamps(data.created, data.lastUpdated, timestampTcDataLoaded);

// handle vendor buttons
if (document.getElementById('show_vendors')) {
const showVendorsButton = document.getElementById('show_vendors');
const vendorsContainerElement = document.getElementById('vendors_container');
showVendorsButton.onclick = () => {
if (vendorsContainerElement.classList.contains('hidden')) {
showHiddenElement('vendors_container');
loadVendors(data.vendorConsents);
showVendorsButton.innerText = 'Hide';
} else {
showVendorsButton.innerText = 'Show vendors';
hideElement('vendors_container');
}
};
}
}

function getActiveTabStorage() {
Expand Down Expand Up @@ -229,7 +263,6 @@ getActiveTabStorage();

// ----------------------------- OLD LOGIC -----------------------------
let cmpLocatorFound = false;
let vendorListVersion = 2;
let consentString = null;

const descriptions = ['Information storage and access', 'Personalisation', 'Ad selection, delivery, reporting', 'Content selection, delivery, reporting', 'Measurement'];
Expand Down Expand Up @@ -352,7 +385,7 @@ function update_with_consent_string_data(consentString) {
vendorListVersion = parseInt(consentString.vendorListVersion);
if (document.title === 'Cookie Glasses') { // this part is unecessary if popup is not open
if (consentString.allowedVendorIds.length === 0) {
document.getElementById('show_vendors').classList.add('hidden');
// document.getElementById('show_vendors').classList.add('hidden');
katie-ta marked this conversation as resolved.
Show resolved Hide resolved
}
document.getElementById('cmplocator_found').classList.add('hidden');
document.getElementById('nothing_found').classList.add('hidden');
Expand Down Expand Up @@ -403,81 +436,6 @@ function update_with_consent_string_data(consentString) {
}
}

function findVendor(id, vendorList) {
for (vendor in vendorList.vendors) {
if (vendorList.vendors[vendor].id == id) {
return vendorList.vendors[vendor];
}
}
return null;
}

function showVendors(vendorList) {
let vendors = '';
const vendorNames = [];
let id;
// eslint-disable-next-line no-restricted-syntax
for (id in consentString.allowedVendorIds) {
const vendor = findVendor(consentString.allowedVendorIds[id], vendorList);
let vendorName;
if (vendor == null) {
vendorName = `{Incorrect vendor, ID ${id}}`;
} else {
vendorName = vendor.name;
if (vendor.purposeIds.length === 0) {
vendorName += ' [*]';
}
}
vendorNames.push(vendorName);
}
vendors = '\r\nVendors ([*] indicates that vendors relies on legitimates interests only):\r\n';
let vendorName;
// eslint-disable-next-line no-restricted-syntax
for (vendorName in vendorNames.sort()) {
vendors += `${vendorNames[vendorName]}\r\n`;
}
document.getElementById('vendors').textContent = vendors;
document.getElementById('show_vendors').classList.add('hidden');
}

function fetchVendorList() {
const req = new Request(`https://vendor-list.consensu.org/v${vendorListVersion}/vendor-list.json`, {
method: 'GET',
headers: { Accept: 'application/json' },
redirect: 'follow',
referrer: 'client',
});
console.log('fetchVendorList', req);
fetch(req).then((response) => response.json()).then((data) => {
const a = {};
a[`vendorList_${vendorListVersion}`] = data;
api.storage.local.set(a);
showVendors(data);
}).catch((error) => {
console.log('Error fetching vendor list: ', error);
// TODO: surface generic error message in pop-up
});
}

function loadVendors() {
const vendorListName = `vendorList_${vendorListVersion}`;
api.storage.local.get([`vendorList_${vendorListVersion}`], (result) => {
// document.getElementById('vendors').classList.remove('hidden');
if (result[vendorListName] === undefined) {
// vendorList is not in localstorage, load it from IAB's website
document.getElementById('vendors').appendChild(document.createTextNode('Loading vendor list...'));
fetchVendorList();
} else {
// vendorList is in localsstorage
showVendors(result[vendorListName]);
}
});
}

if (document.getElementById('show_vendors')) {
document.getElementById('show_vendors').onclick = loadVendors;
}

if (document.getElementById('decode_cs')) {
document.getElementById('decode_cs').onclick = function () {
const raw_consent_string = document.getElementById('cs_to_decode').value;
Expand Down
22 changes: 17 additions & 5 deletions src/popup/ucookie.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ h3 {
margin-bottom: 3px;
}

textarea {
width: 480px;
margin-bottom: 5px;
}

.total_nb_container{
margin-top: 14px;
margin-bottom: 14px;
Expand Down Expand Up @@ -78,16 +83,23 @@ h3 {
background-color: #EAEA9D;
}

textarea {
width: 480px;
margin-bottom: 5px;
}

.identified_cmp {
color: rgb(6, 103, 116);
font-size: 16px;
}

#vendors_container {
border: 1px solid rgb(218, 218, 218);
border-radius: 5px;
overflow-y: auto;
max-height: 200px;
}

#vendors_list {
margin-top: 8px;
padding-left: 28px;
}

#nb_purposes, #nb_vendors, #cmp {
font-weight: bold;
}
Expand Down
7 changes: 5 additions & 2 deletions src/popup/ucookie.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,16 @@ <h2>Vendors</h2>
<span id='nb_vendors' class="total_nb"></span> total vendors consented to.
<button id="show_vendors">Show vendors</button>
</div>
<div id="vendors_container" class="hidden">
[*] indicates that vendors relies on legitimates interests only
<ul id="vendors_list"></ul>
</div>
</div>
<div class="content-container">
<h2>Purposes</h2>
<div class="total_nb_container">
<span><span id='nb_purposes' class="total_nb"></span> / 10 purposes with consent</span>
<button id="show_purposes" class="show_button">Show purposes</button>
<button id="show_purposes">Show purposes</button>
</div>

<div class="hidden" id="purposes_list">
Expand All @@ -69,7 +73,6 @@ <h2>Purposes</h2>
TCF String Last Updated: <i><span id='last_updated'></span></i><br />
TCF String Last Fetched: <i><span id='last_fetched'></span></i><br />
</div>
<span id='vendors' class="hidden"></span>
</div>
<br />
<a href="#" id="open_decoder" title="Open manual consent string decoder"><img src="img/Octicons-tools.png" class="icon"></a>
Expand Down