Skip to content
Snippets Groups Projects
state-manager.js 6.95 KiB
Newer Older
/**
 * State Manager
 * Belongs to Decentraleyes.
 *
 * @author      Thomas Rientjes
 * @since       2017-03-10
 * @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/.
 */

'use strict';

/**
 * State Manager
 */

var stateManager = {};

/**
 * Public Methods
 */

stateManager.registerInjection = function (tabIdentifier, injection) {

    let injectionIdentifier, registeredTab, injectionCount;

    injectionIdentifier = injection.source + injection.path + injection.version;
    registeredTab = stateManager.tabs[tabIdentifier];

    registeredTab.injections[injectionIdentifier] = injection;
    injectionCount = Object.keys(registeredTab.injections).length || 0;

    if (stateManager.showIconBadge === true) {
        if (injectionCount > 0) {
            wrappers.setBadgeText({
                'tabId': tabIdentifier,
                'text': injectionCount.toString()
            wrappers.setBadgeText({
                'tabId': tabIdentifier,
                'text': ''
    }

    if (isNaN(interceptor.amountInjected)) {

        chrome.storage.local.get(Setting.AMOUNT_INJECTED, function (items) {

            interceptor.amountInjected = items.amountInjected;

            chrome.storage.local.set({
                'amountInjected': ++interceptor.amountInjected
            });
        });

    } else {

        chrome.storage.local.set({
            'amountInjected': ++interceptor.amountInjected
        });
    }
};

stateManager.addDomainToWhitelist = function (domain) {

    return new Promise((resolve) => {

        let whitelistedDomains = requestAnalyzer.whitelistedDomains;
        whitelistedDomains[domain] = true;

        chrome.storage.local.set({whitelistedDomains}, resolve);
    });
};

stateManager.deleteDomainFromWhitelist = function (domain) {

    return new Promise((resolve) => {

        let whitelistedDomains = requestAnalyzer.whitelistedDomains;
        delete whitelistedDomains[domain];

        chrome.storage.local.set({whitelistedDomains}, resolve);
    });
};

/**
 * Private Methods
 */

stateManager._createTab = function (tab) {

    let tabIdentifier, requestFilters;

    tabIdentifier = tab.id;

    stateManager.tabs[tabIdentifier] = {
        'injections': {}
    };

    requestFilters = {

        'tabId': tabIdentifier,
        'urls': stateManager.validHosts
    };

    chrome.webRequest.onBeforeRequest.addListener(function (requestDetails) {

        let tab = stateManager.tabs[tabIdentifier].details || {};
        return interceptor.handleRequest(requestDetails, tabIdentifier, tab);
    }, requestFilters, [WebRequest.BLOCKING]);
};

stateManager._removeTab = function (tabIdentifier) {
    delete stateManager.tabs[tabIdentifier];
};

stateManager._updateTab = function (details) {

    let tabIdentifier, frameIdentifier;

    tabIdentifier = details.tabId;
    frameIdentifier = details.frameId;

    if (tabIdentifier === -1 || frameIdentifier !== 0) {
        return;
    }

    if (stateManager.showIconBadge === true) {

        wrappers.setBadgeText({
            'tabId': tabIdentifier,
            'text': ''

    if (stateManager.tabs[tabIdentifier]) {
        stateManager.tabs[tabIdentifier].injections = {};
    }
};

stateManager._stripMetadata = function (requestDetails) {

    for (let i = 0; i < requestDetails.requestHeaders.length; ++i) {

        if (requestDetails.requestHeaders[i].name === WebRequest.ORIGIN_HEADER) {
            requestDetails.requestHeaders.splice(i--, 1);
        } else if (requestDetails.requestHeaders[i].name === WebRequest.REFERER_HEADER) {
            requestDetails.requestHeaders.splice(i--, 1);
        }
    }

    return {
        'requestHeaders': requestDetails.requestHeaders
    };
};

stateManager._handleStorageChanged = function (changes) {

    if ('showIconBadge' in changes) {
        stateManager.showIconBadge = changes.showIconBadge.newValue;

        if (changes.showIconBadge.newValue !== true) {

            chrome.tabs.query({}, function (tabs) {
                tabs.forEach(stateManager._removeIconBadgeFromTab);
            });
        }
    }

    if ('stripMetadata' in changes) {

        let onBeforeSendHeaders;

        onBeforeSendHeaders = chrome.webRequest.onBeforeSendHeaders;

        onBeforeSendHeaders.removeListener(stateManager._stripMetadata, {
            'urls': stateManager.validHosts
        }, [WebRequest.BLOCKING, WebRequest.HEADERS]);

        if (changes.stripMetadata.newValue !== false) {
            onBeforeSendHeaders.addListener(stateManager._stripMetadata, {
                'urls': stateManager.validHosts
            }, [WebRequest.BLOCKING, WebRequest.HEADERS]);
};

stateManager._removeIconBadgeFromTab = function (tab) {

    wrappers.setBadgeText({
        'tabId': tab.id,
        'text': ''
/**
 * Initializations
 */

stateManager.requests = {};
stateManager.tabs = {};
stateManager.validHosts = [];

for (let mapping in mappings) {

    let supportedHost = Address.ANY_PROTOCOL + mapping + Address.ANY_PATH;
    stateManager.validHosts.push(supportedHost);
}

chrome.tabs.query({}, function (tabs) {
    tabs.forEach(stateManager._createTab);
});

chrome.storage.local.get('showIconBadge', function (items) {
    stateManager.showIconBadge = items.showIconBadge || true;
});

/**
 * Event Handlers
 */

chrome.tabs.onCreated.addListener(stateManager._createTab);
chrome.tabs.onRemoved.addListener(stateManager._removeTab);

chrome.webRequest.onBeforeRequest.addListener(function (requestDetails) {

    if (requestDetails.tabId !== -1) {

        stateManager.tabs[requestDetails.tabId].details = {
            'url': requestDetails.url
        };
    }

}, {'types': ['main_frame'], 'urls': [Address.ANY]});

chrome.webNavigation.onCommitted.addListener(stateManager._updateTab, {
    'url': [{'urlContains': ':'}]
});

chrome.webRequest.onErrorOccurred.addListener(function (requestDetails) {

    if (stateManager.requests[requestDetails.requestId]) {
        delete stateManager.requests[requestDetails.requestId];
    }

}, {'urls': [Address.ANY]});

chrome.webRequest.onBeforeRedirect.addListener(function (requestDetails) {

    let knownRequest = stateManager.requests[requestDetails.requestId];

    if (knownRequest) {

        stateManager.registerInjection(knownRequest.tabIdentifier, knownRequest.targetDetails);
        delete stateManager.requests[requestDetails.requestId];
    }

}, {'urls': [Address.ANY]});
chrome.storage.local.get({'stripMetadata': true}, function (options) {

    if (options === null || options.stripMetadata !== false) {

        chrome.webRequest.onBeforeSendHeaders.addListener(stateManager._stripMetadata, {
            'urls': stateManager.validHosts
        }, [WebRequest.BLOCKING, WebRequest.HEADERS]);
    }
});

chrome.storage.onChanged.addListener(stateManager._handleStorageChanged);