Skip to content
Snippets Groups Projects
request-analyzer.js 4.02 KiB
Newer Older
Thomas Rientjes's avatar
Thomas Rientjes committed
/**
 * Request Analyzer
 * Belongs to Decentraleyes.
 *
 * @author      Thomas Rientjes
 * @since       2014-05-30
 * @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';

/**
 * Imports
 */

var preferences = require('sdk/simple-prefs').prefs;

/**
 * Resource version mappings.
 * @var {object} mappings
 */
Thomas Rientjes's avatar
Thomas Rientjes committed
var mappings = require('./mappings');

/**
 * Variables
 */

var whitelistedDomains = [];

/**
 * Initializations
 */

applyWhitelistPreference();

/**
 * Event Handlers
 */

require('sdk/simple-prefs').on('domainWhitelist', applyWhitelistPreference);


Thomas Rientjes's avatar
Thomas Rientjes committed
/**
 * Public Methods
 */

function isValidCandidate(httpChannel) {

    if (mappings[httpChannel.URI.host] === undefined) {
        return false;
    }
Thomas Rientjes's avatar
Thomas Rientjes committed

    var requestDomain = null;
    if (httpChannel.loadInfo && httpChannel.loadInfo.loadingDocument && httpChannel.loadInfo.loadingDocument.domain) {
        requestDomain = normalizeDomain(httpChannel.loadInfo.loadingDocument.domain);
    } else if (httpChannel.referrer && httpChannel.referrer.host) {
        requestDomain = normalizeDomain(httpChannel.referrer.host);
    }
    if (whitelistedDomains.length > 0 && requestDomain !== null) {
        for (let domain of whitelistedDomains) {
            if (domain === requestDomain) {
                // Remove referer header from request.
                httpChannel.setRequestHeader('Referer', null, false);
                return false;
    return httpChannel.requestMethod === 'GET';
Thomas Rientjes's avatar
Thomas Rientjes committed
}

function getLocalTarget(channelHost, channelPath) {

    var basePath, hostMappings, resourceMappings, localTarget;

    hostMappings = mappings[channelHost];

    // Ignore mapping files.
    if (channelPath.indexOf('.min.js.map') > -1) {
        return false;
    }
Thomas Rientjes's avatar
Thomas Rientjes committed

    if (channelPath.indexOf('.min.map') > -1) {
        return false;
    }
Thomas Rientjes's avatar
Thomas Rientjes committed

    basePath = matchBasePath(hostMappings, channelPath);
Thomas Rientjes's avatar
Thomas Rientjes committed

    if (!basePath) {
        return false;
    }
Thomas Rientjes's avatar
Thomas Rientjes committed

    resourceMappings = hostMappings[basePath];
    localTarget = matchResourcePath(resourceMappings, basePath, channelPath);
Thomas Rientjes's avatar
Thomas Rientjes committed

    if (!localTarget) {
        return false;
    }

    return localTarget;
Thomas Rientjes's avatar
Thomas Rientjes committed
}

/**
 * Exports
 */

exports.isValidCandidate = isValidCandidate;
exports.getLocalTarget = getLocalTarget;

/**
 * Private Methods
 */

function matchBasePath(hostMappings, channelPath) {

    for (let basePath in hostMappings) {

        if (hostMappings.hasOwnProperty(basePath)) {
Thomas Rientjes's avatar
Thomas Rientjes committed

            if (channelPath.startsWith(basePath)) {
                return basePath;
            }
        }
    }
Thomas Rientjes's avatar
Thomas Rientjes committed

    return false;
Thomas Rientjes's avatar
Thomas Rientjes committed
}

function matchResourcePath(resourceMappings, basePath, channelPath) {

    var resourcePath, versionNumber, resourcePattern;

    resourcePath = channelPath.replace(basePath, '');

    versionNumber = resourcePath.match(/(?:\d{1,2}\.){1,3}\d{1,2}/);
    resourcePattern = resourcePath.replace(versionNumber, '{version}');
Thomas Rientjes's avatar
Thomas Rientjes committed

    for (let resourceMold in resourceMappings) {
Thomas Rientjes's avatar
Thomas Rientjes committed

        if (resourceMappings.hasOwnProperty(resourceMold)) {
Thomas Rientjes's avatar
Thomas Rientjes committed

            if (resourcePattern.startsWith(resourceMold)) {
Thomas Rientjes's avatar
Thomas Rientjes committed

                var localTarget = {
                    path: resourceMappings[resourceMold].path,
                    type: resourceMappings[resourceMold].type
                };
Thomas Rientjes's avatar
Thomas Rientjes committed

                // Fill in the appropriate version number.
                localTarget.path = localTarget.path.replace('{version}', versionNumber);
Thomas Rientjes's avatar
Thomas Rientjes committed

                return localTarget;
            }
        }
    }
Thomas Rientjes's avatar
Thomas Rientjes committed

    return false;
Thomas Rientjes's avatar
Thomas Rientjes committed
}

function normalizeDomain(domain) {

    domain = domain.toLowerCase().trim();

    if (domain.startsWith('www.')) {
        domain = domain.slice(4);
    }

    return domain;
}

function applyWhitelistPreference() {

    whitelistedDomains = [];

    //noinspection JSUnresolvedVariable
    preferences.domainWhitelist.split(';').forEach(function(domain, index) {
        whitelistedDomains[index] = normalizeDomain(domain);
    });
}