Skip to content
Snippets Groups Projects
popup.js 9.91 KiB
Newer Older
 * Popup Page
 * Belongs to Decentraleyes.
 *
 * @author      Thomas Rientjes
 * @since       2016-08-09
 * @license     MPL 2.0
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/.
 */

import Helpers from '../shared/code/helpers.js';
 * Private Functions
const _groupResourceInjections = (injections) => {
    return Object.values(injections).reduce((accumulator, injection) => {
        accumulator[injection.source] = accumulator[injection.source] ?? [];
        accumulator[injection.source].push(injection);
        return accumulator;
const _createInjectionGroupHeaderElement = (source, injections) => {
    let injectionGroupHeaderElement, badgeElement, badgeTextNode, cdnNameTextNode;
    injectionGroupHeaderElement = document.createElement('li');
    injectionGroupHeaderElement.setAttribute('class', 'list-item');
    badgeElement = document.createElement('span');
    badgeElement.setAttribute('class', 'badge');
    badgeTextNode = document.createTextNode(injections.length);
    badgeElement.appendChild(badgeTextNode);
    cdnNameTextNode = document.createTextNode(Helpers.determineCdnName(source));
    injectionGroupHeaderElement.appendChild(badgeElement);
    injectionGroupHeaderElement.appendChild(cdnNameTextNode);
    return injectionGroupHeaderElement;
};
const _createInjectionElement = (injection) => {
    let injectionElement, filename, name, nameTextNode, noteElement, noteTextNode;
    injectionElement = document.createElement('li');
    injectionElement.setAttribute('class', 'sublist-item');
    filename = Helpers.extractFilenameFromPath(injection.path);
    name = Helpers.determineResourceName(filename);
    nameTextNode = document.createTextNode(`- ${name}`);
    injectionElement.appendChild(nameTextNode);
    noteElement = document.createElement('span');
    noteElement.setAttribute('class', 'side-note');
    noteTextNode = document.createTextNode(` v${injection.version}`);
    noteElement.appendChild(noteTextNode);
    injectionElement.appendChild(noteElement);
    return injectionElement;
const _createInjectionGroupElement = (source, injections) => {
    let injectionGroupElement;
    injectionGroupElement = document.createElement('ul');
    injectionGroupElement.setAttribute('class', 'sublist');
    for (const injection of injections) {
        const injectionElement = _createInjectionElement(injection);
        injectionGroupElement.appendChild(injectionElement);
    }
    return injectionGroupElement;
};
const _createInjectionOverviewElement = (groupedInjections) => {
    const injectionOverviewElement = document.createElement('ul');
    injectionOverviewElement.setAttribute('class', 'list');
    for (const [source, injections] of Object.entries(groupedInjections)) {
        let injectionGroupHeaderElement, injectionGroupElement;
        injectionGroupHeaderElement = _createInjectionGroupHeaderElement(source, injections);
        injectionGroupElement = _createInjectionGroupElement(source, injections);
        injectionOverviewElement.appendChild(injectionGroupHeaderElement);
        injectionOverviewElement.appendChild(injectionGroupElement);
    return injectionOverviewElement;
const _renderInjectionPanel = (groupedInjections) => {
    let websiteContextElement, injectionOverviewElement;
    websiteContextElement = document.getElementById('website-context');
    injectionOverviewElement = _createInjectionOverviewElement(groupedInjections);
    websiteContextElement.append(injectionOverviewElement);
};
const _close = async () => {
    const platform = await chrome.runtime.getPlatformInfo();
    if (platform.os === chrome.runtime.PlatformOs.ANDROID) {
        const activeTab = await chrome.tabs.getCurrent();
        if (activeTab) {
            chrome.tabs.remove(activeTab.id);
        } else {
            window.close();
        }
    } else {
        window.close();
    }
/**
 * Event Handlers
 */
const _onTestingUtilityLinkClicked = (event) => {
    if (event.button === 0 || event.button === 1) {
        chrome.tabs.create({
            'url': 'https://decentraleyes.org/test',
            'active': (event.button === 0)
    if (event.button === 0) {
        window.close();
    }
const _onOptionsButtonClicked = async () => {
    const platform = await chrome.runtime.getPlatformInfo();
    if (platform.os === chrome.runtime.PlatformOs.ANDROID) {
        chrome.tabs.create({
            'url': chrome.runtime.getURL('pages/options/options.html'),
            'active': true
        return window.close();
        chrome.runtime.openOptionsPage();
        return window.close();
    }
const _renderNonContextualContents = async () => {
    let versionLabelElement, counterElement, testingUtilityLinkElement, optionsButtonElement, amountInjected;
    versionLabelElement = document.getElementById('version-label');
    counterElement = document.getElementById('injection-counter');
    testingUtilityLinkElement = document.getElementById('testing-utility-link');
    optionsButtonElement = document.getElementById('options-button');
    versionLabelElement.innerText = Helpers.determineVersion();
    amountInjected = await Helpers.delegateAction('statistics:get-amount-injected');
    counterElement.innerText = Helpers.formatNumber(amountInjected.value);
    testingUtilityLinkElement.addEventListener('mouseup', _onTestingUtilityLinkClicked);
    optionsButtonElement.addEventListener('mouseup', _onOptionsButtonClicked);
    testingUtilityLinkElement.addEventListener('keydown', (event) => {
        const enterOrSpaceKeyPressed = Helpers.enterOrSpaceKeyPressed(event);
        if (enterOrSpaceKeyPressed) {
            chrome.tabs.create({
                'url': 'https://decentraleyes.org/test'
            });
            window.close();
        }
    });
    optionsButtonElement.addEventListener('keydown', (event) => {
        const enterOrSpaceKeyPressed = Helpers.enterOrSpaceKeyPressed(event);
        if (enterOrSpaceKeyPressed) {
            chrome.runtime.openOptionsPage();
            return window.close();
const _onProtectionToggled = async () => {
    let bypassCache, activeTab;
    bypassCache = (typeof browser === 'undefined');
    activeTab = await Helpers.determineActiveTab();
    chrome.tabs.reload(activeTab.id, {bypassCache});
    _close();
const _enableProtection = async () => {
    let activeTab, tabDomain;
    activeTab = await Helpers.determineActiveTab();
    tabDomain = await Helpers.delegateAction('domain:extract-from-url', activeTab.url);
    await Helpers.delegateAction('domain:remove-from-whitelist', tabDomain);
    _onProtectionToggled();
const _disableProtection = async () => {
    let activeTab, tabDomain;
    activeTab = await Helpers.determineActiveTab();
    tabDomain = await Helpers.delegateAction('domain:extract-from-url', activeTab.url);
    await Helpers.delegateAction('domain:add-to-whitelist', tabDomain);
    _onProtectionToggled();
};
const _renderDomainWhitelistPanel = async (domain) => {
    let websiteContextElement, protectionToggleElement, domainIndicatorElement, domainIsWhitelisted;
    websiteContextElement = document.getElementById('website-context');
    protectionToggleElement = document.getElementById('protection-toggle-button');
    domainIndicatorElement = document.getElementById('domain-indicator');
    protectionToggleElement.setAttribute('dir', Helpers.determineScriptDirection());
    domainIndicatorElement.innerText = domain;
    domainIsWhitelisted = await Helpers.delegateAction('domain:is-whitelisted', domain);
    if (domainIsWhitelisted === true) {
        const enableProtectionTitle = chrome.i18n.getMessage('enableProtectionTitle');
        protectionToggleElement.setAttribute('class', 'button button-toggle');
        protectionToggleElement.addEventListener('click', _enableProtection);
        protectionToggleElement.setAttribute('title', enableProtectionTitle);
        protectionToggleElement.addEventListener('keydown', (event) => {
            const enterOrSpaceKeyPressed = Helpers.enterOrSpaceKeyPressed(event);
            if (enterOrSpaceKeyPressed) {
                _enableProtection();
            }
        });
        const disableProtectionTitle = chrome.i18n.getMessage('disableProtectionTitle');
        protectionToggleElement.setAttribute('class', 'button button-toggle active');
        protectionToggleElement.addEventListener('click', _disableProtection);
        protectionToggleElement.setAttribute('title', disableProtectionTitle);
        protectionToggleElement.addEventListener('keydown', (event) => {
            const enterOrSpaceKeyPressed = Helpers.enterOrSpaceKeyPressed(event);
            if (enterOrSpaceKeyPressed) {
                _disableProtection();
            }
    websiteContextElement.classList.remove('hidden');
const _renderContextualContents = async () => {
    let activeTab, tabDomain, tabContext, groupedInjections;
    activeTab = await Helpers.determineActiveTab();
    tabDomain = await Helpers.delegateAction('domain:extract-from-url', activeTab.url);
    if (tabDomain !== null) {
        await _renderDomainWhitelistPanel(tabDomain);
    }
    tabContext = await Helpers.delegateAction('tab-context:get', activeTab.id);
    groupedInjections = _groupResourceInjections(tabContext.injections);
    if (Object.keys(groupedInjections).length > 0) {
        _renderInjectionPanel(groupedInjections);
    }
const _onDocumentLoaded = async () => {

    Helpers.applyI18nContentToDocument(document);
    Helpers.applyI18nTitlesToDocument(document);
    await _renderNonContextualContents();
    await _renderContextualContents();
    Helpers.unhideDocumentContents(document);
document.addEventListener('DOMContentLoaded', _onDocumentLoaded);