<commit_before>'use strict';
const util = require('util');
const _ = require('./helpers');

const CommandUtil = {
  findItemInEquipment, findItemInRoom,
  findItemInInventory, hasScript,
  findNpcInRoom      , inSameRoom,
  parseDot           ,
};

/**
 * Takes an object and name of event to emit and tells you if it has a listener.
 * @param  Obj
 * @param  String name of event
 * @return Boolean if event has listener
 */

function hasScript(entity, event){
  return entity._events && entity._events[event];
}

/**
 * @param Player|NPC entity
 * @param Player     target
 * @return boolean   True if they are in the same room, else false.
 */
function inSameRoom(entity, target) {
  if (target) {
    if (entity.getName) { // Handle players
      const notSameName = target.getName() !== entity.getName();
      const sameLocation = target.getLocation() === entity.getLocation();
      return notSameName && sameLocation;
    } else if (entity.getShortDesc) { // Handle NPCs and items
      return entity.getRoom() === target.getLocation();
    }
  }
}

/**
 * Find an item in a room based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param Being player | npc
 * @param boolean hydrate Whether to return the id or a full object
 * @return string UUID of the item
 */

function findItemInEquipment(lookString, being, hydrate) {
  const equipment = being.getInventory().filter(i => i.isEquipped());
  util.log('eq::::::', equipment);
  const thing = CommandUtil.parseDot(lookString, equipment,
    function(item) {
      return item && item.hasKeyword(this.keyword, being.getLocale());
    });

  return thing ? (hydrate ? thing : thing.getUuid()) : false;
}

/**
 * Find an item in a room based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param Room   room
 * @param Player player
 * @param boolean hydrate Whether to return the id or a full object
 * @return string UUID of the item
 */
function findItemInRoom(items, lookString, room, player, hydrate) {
  hydrate = hydrate || false;
  let thing = CommandUtil.parseDot(lookString, room.getItems(), function(
    item) {
    let found = items.get(item);
    return found && found.hasKeyword(this.keyword, 'en');
  });

  return thing ? (hydrate ? items.get(thing) : thing) : false;
}

/**
 * Find an npc in a room based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param Room   room
 * @param Player player
 * @param boolean hydrate Whether to return the id or a full object
 * @return string UUID of the item
 */
function findNpcInRoom(npcs, lookString, room, player, hydrate) {
  hydrate = hydrate || false;
  let thing = CommandUtil.parseDot(lookString, room.getNpcs(),
    function (id) {
      let npc = npcs.get(id);
      return npc && npc.hasKeyword(this.keyword, 'en');
    }
  );

  return thing ? (hydrate ? npcs.get(thing) : thing) : false;
}

/**
 * Find an item in inventory based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param object being This could be a player or NPC. Though most likely player
 * @return string UUID of the item
 */
function findItemInInventory(lookString, being, hydrate) {
  hydrate = hydrate || false;
  let thing = CommandUtil.parseDot(lookString, being.getInventory(),
    function (item) {
      return item && item.hasKeyword(this.keyword, being.getLocale());
    });

  return thing ? (hydrate ? thing : thing.getUuid()) : false;
}

/**
 * Parse 3.blah item notation
 * @param string arg    The actual 3.blah string
 * @param Array objects The array of objects to search in
 * @param Function filterFunc Function to filter the list
 * @return object
 */
function parseDot(arg, objects, filterFunc) {
  if (!arg) {
    util.log("ERROR: No arg passed into parseDot: ", arguments);
    return;
  }
  let keyword = _.firstWord(arg);
  let multi = false;
  let nth = null;

  // Are they trying to get the nth item of a keyword?
  if (/^\d+\./.test(keyword)) {
    nth = parseInt(keyword.split('.')[0], 10);
    keyword = keyword.split('.')[1];
    multi = true;
  }

  const found = objects.filter(filterFunc, { keyword, nth });

  if (!found.length) { return false; }

  const areMultiples = multi && !isNaN(nth) && nth && nth <= found.length
  return areMultiples ?
    found[nth - 1] :
    found[0];

}

exports.CommandUtil = CommandUtil;
<commit_msg>Remove debug log<commit_after>'use strict';
const util = require('util');
const _ = require('./helpers');

const CommandUtil = {
  findItemInEquipment, findItemInRoom,
  findItemInInventory, hasScript,
  findNpcInRoom      , inSameRoom,
  parseDot           ,
};

/**
 * Takes an object and name of event to emit and tells you if it has a listener.
 * @param  Obj
 * @param  String name of event
 * @return Boolean if event has listener
 */

function hasScript(entity, event){
  return entity._events && entity._events[event];
}

/**
 * @param Player|NPC entity
 * @param Player     target
 * @return boolean   True if they are in the same room, else false.
 */
function inSameRoom(entity, target) {
  if (target) {
    if (entity.getName) { // Handle players
      const notSameName = target.getName() !== entity.getName();
      const sameLocation = target.getLocation() === entity.getLocation();
      return notSameName && sameLocation;
    } else if (entity.getShortDesc) { // Handle NPCs and items
      return entity.getRoom() === target.getLocation();
    }
  }
}

/**
 * Find an item in a room based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param Being player | npc
 * @param boolean hydrate Whether to return the id or a full object
 * @return string UUID of the item
 */

function findItemInEquipment(lookString, being, hydrate) {
  const equipment = being.getInventory().filter(i => i.isEquipped());
  const thing = CommandUtil.parseDot(lookString, equipment,
    function(item) {
      return item && item.hasKeyword(this.keyword, being.getLocale());
    });

  return thing ? (hydrate ? thing : thing.getUuid()) : false;
}

/**
 * Find an item in a room based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param Room   room
 * @param Player player
 * @param boolean hydrate Whether to return the id or a full object
 * @return string UUID of the item
 */
function findItemInRoom(items, lookString, room, player, hydrate) {
  hydrate = hydrate || false;
  let thing = CommandUtil.parseDot(lookString, room.getItems(), function(
    item) {
    let found = items.get(item);
    return found && found.hasKeyword(this.keyword, 'en');
  });

  return thing ? (hydrate ? items.get(thing) : thing) : false;
}

/**
 * Find an npc in a room based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param Room   room
 * @param Player player
 * @param boolean hydrate Whether to return the id or a full object
 * @return string UUID of the item
 */
function findNpcInRoom(npcs, lookString, room, player, hydrate) {
  hydrate = hydrate || false;
  let thing = CommandUtil.parseDot(lookString, room.getNpcs(),
    function (id) {
      let npc = npcs.get(id);
      return npc && npc.hasKeyword(this.keyword, 'en');
    }
  );

  return thing ? (hydrate ? npcs.get(thing) : thing) : false;
}

/**
 * Find an item in inventory based on the syntax
 *   things like: get 2.thing or look 6.thing or look thing
 * @param string lookString
 * @param object being This could be a player or NPC. Though most likely player
 * @return string UUID of the item
 */
function findItemInInventory(lookString, being, hydrate) {
  hydrate = hydrate || false;
  let thing = CommandUtil.parseDot(lookString, being.getInventory(),
    function (item) {
      return item && item.hasKeyword(this.keyword, being.getLocale());
    });

  return thing ? (hydrate ? thing : thing.getUuid()) : false;
}

/**
 * Parse 3.blah item notation
 * @param string arg    The actual 3.blah string
 * @param Array objects The array of objects to search in
 * @param Function filterFunc Function to filter the list
 * @return object
 */
function parseDot(arg, objects, filterFunc) {
  if (!arg) {
    util.log("ERROR: No arg passed into parseDot: ", arguments);
    return;
  }
  let keyword = _.firstWord(arg);
  let multi = false;
  let nth = null;

  // Are they trying to get the nth item of a keyword?
  if (/^\d+\./.test(keyword)) {
    nth = parseInt(keyword.split('.')[0], 10);
    keyword = keyword.split('.')[1];
    multi = true;
  }

  const found = objects.filter(filterFunc, { keyword, nth });

  if (!found.length) { return false; }

  const areMultiples = multi && !isNaN(nth) && nth && nth <= found.length
  return areMultiples ?
    found[nth - 1] :
    found[0];

}

exports.CommandUtil = CommandUtil;
<|endoftext|>


<commit_before>import _     from 'lodash';
import AWS   from 'aws-sdk';
import chalk from 'chalk';

import config from '../config';

function createService(taskDefinition, region) {
    let ecs = getECS(region);
    let cluster = config.get('cluster');
    let service = config.get('service');

    console.log(chalk.dim(`service ${service.name} was not found in ${region}, creating...`));

    return ecs.createService({
        desiredCount: service.count,
        serviceName: service.name,
        taskDefinition,
        cluster,
        deploymentConfiguration: {
            maximumPercent: service.maximumPercent,
            minimumHealthyPercent: service.minimumPercent
        }
    }).promise()
    .then((result) => {
        console.log(`    ${chalk.bold.green('\u2713')} service ${result.service.serviceName} created in ${region}`);
        return result;
    });
}

function getECS(region) {
    return new AWS.ECS({
        region
    });
}

function getRegions() {
    let regions = config.get('regions');
    if (_.isString(regions)) {
        regions = [regions];
    }

    return regions;
}

function updateService(taskDefinition, region) {
    let ecs = getECS(region);
    let cluster = config.get('cluster');
    let service = config.get('service');

    console.log(chalk.dim(`service ${service.name} found in ${region}, updating...`));

    return ecs.updateService({
        serviceName: service.name,
        cluster,
        taskDefinition
    }).promise()
    .then((result) => {
        console.log(`    ${chalk.bold.green('\u2713')} service ${result.service.serviceName} updated in ${region}`);
        return result;
    });
}

export function createTaskDefinition(imageUri) {
    if (!imageUri) {
        throw new TypeError('imageUri can not be null');
    }

    let task = {};

    task.family = config.get('task.name');
    task.networkMode = config.get('task.networkMode');

    let container = {};
    container.name = config.get('task.container.name');
    container.image = imageUri;
    if (config.get('task.container.cpu')) {
        container.cpu = config.get('task.container.cpu');
    }
    if (config.get('task.container.memory')) {
        container.memory = config.get('task.container.memory');
    }
    if (config.get('task.container.memoryReservation')) {
        container.memoryReservation = config.get('task.container.memoryReservation');
    }
    container.portMappings = _.map(config.get('task.container.ports'), (port) => {
        let def = {};
        if (_.isString(port)) {
            def.containerPort = parseInt(port, 10);
        } else if (_.isNumber(port)) {
            def.containerPort = port;
        } else {
            if (!port.container) { throw new TypeError('port definition must specify container port'); }

            def.containerPort = port.container;
            if (port.host) {
                def.hostPort = port.host;
            }
        }

        if (port.protocol) {
            def.protocol = port.protocol;
        } else {
            def.protocol = 'tcp';
        }

        return def;
    });

    container.environment = _.map(config.get('task.container.environment'), (value, key) => {
        return {
            name: key,
            value
        };
    });

    // Validate the container definition
    if (!container.memory && !container.memoryReservation) {
        throw new TypeError('task container must specify memory and/or memoryReservation');
    }

    if (container.memory < container.memoryReservation) {
        throw new TypeError('task container memory must be greater than memoryReservation');
    }

    task.containerDefinitions = [container];

    return Promise.resolve(task);
}

export function ensureClusterExists() {
    let regions = getRegions();
    let cluster = config.get('cluster');

    console.log(chalk.dim(`ensuring cluster ${cluster} exists in ${regions.join(', ')}`));

    return Promise.all(_.map(regions, (region) => {
        let ecs = getECS(region);

        return ecs.describeClusters({
            clusters: [cluster]
        }).promise()
        .then((result) => {
            if (result.clusters.length > 0 && result.clusters[0].status === 'ACTIVE') {
                // Cluster was found, we can just return
                console.log(`    ${chalk.bold.green('\u2713')} cluster ${cluster} found in ${region}`);
                return;
            }

            console.log(chalk.dim(`creating cluster ${cluster} in ${region}`));
            return ecs.createCluster({
                clusterName: cluster
            }).promise()
            .then((result) => {
                console.log(`    ${chalk.bold.green('\u2713')} cluster ${result.cluster.clusterName} created in ${region}`);
            });
        });
    }))
    .then(() => { console.log(); });
}

export function runService(taskDefinition, region) {
    let cluster = config.get('cluster');
    let service = config.get('service');

    console.log(chalk.dim(`starting service ${service.name} for cluster ${cluster} in ${region}`));

    let ecs = getECS(region);

    console.log(chalk.dim(`ensuring service exists in ${region}`));
    return ecs.describeServices({
        services: [service.name],
        cluster
    }).promise()
    .then((result) => {
        if (result.services.length > 0 && result.services[0].status === 'ACTIVE') {
            // Service was found, we can update it
            return updateService(taskDefinition, region);
        }

        return createService(taskDefinition, region);
    })
    .then(({service}) => {
        return {
            service,
            region
        };
    });
}

export function registerTask(task) {
    let regions = getRegions();

    console.log(chalk.dim(`registering task definition in ${regions.join(', ')}`));

    return Promise.all(_.map(regions, (region) => {
        let ecs = getECS(region);

        return ecs.registerTaskDefinition(task).promise()
        .then((result) => {
            let arn = result.taskDefinition.taskDefinitionArn;
            let family = task.family;
            let revision = arn.substring(arn.lastIndexOf(':') + 1);
            console.log(`    ${chalk.bold.green('\u2713')} task ${family}:${revision} created in ${region}`);

            return {
                region,
                task: result.taskDefinition.taskDefinitionArn
            };
        })
        .then((tasks) => {
            console.log();
            return tasks;
        });
    }));
}

export function waitForStable(service, region) {
    let ecs = getECS(region);

    return ecs.waitFor('servicesStable', {
        services: [service.serviceName],
        cluster: config.get('cluster')
    }).promise()
    .then((result) => {
        console.log(`    ${chalk.bold.green('\u2713')} service ${service.serviceName} ${chalk.bold.green('STABLE')} in ${region}`);
        return result;
    });
}
<commit_msg>:bug: fix(ecs): return all tasks<commit_after>import _     from 'lodash';
import AWS   from 'aws-sdk';
import chalk from 'chalk';

import config from '../config';

function createService(taskDefinition, region) {
    let ecs = getECS(region);
    let cluster = config.get('cluster');
    let service = config.get('service');

    console.log(chalk.dim(`service ${service.name} was not found in ${region}, creating...`));

    return ecs.createService({
        desiredCount: service.count,
        serviceName: service.name,
        taskDefinition,
        cluster,
        deploymentConfiguration: {
            maximumPercent: service.maximumPercent,
            minimumHealthyPercent: service.minimumPercent
        }
    }).promise()
    .then((result) => {
        console.log(`    ${chalk.bold.green('\u2713')} service ${result.service.serviceName} created in ${region}`);
        return result;
    });
}

function getECS(region) {
    return new AWS.ECS({
        region
    });
}

function getRegions() {
    let regions = config.get('regions');
    if (_.isString(regions)) {
        regions = [regions];
    }

    return regions;
}

function updateService(taskDefinition, region) {
    let ecs = getECS(region);
    let cluster = config.get('cluster');
    let service = config.get('service');

    console.log(chalk.dim(`service ${service.name} found in ${region}, updating...`));

    return ecs.updateService({
        serviceName: service.name,
        cluster,
        taskDefinition
    }).promise()
    .then((result) => {
        console.log(`    ${chalk.bold.green('\u2713')} service ${result.service.serviceName} updated in ${region}`);
        return result;
    });
}

export function createTaskDefinition(imageUri) {
    if (!imageUri) {
        throw new TypeError('imageUri can not be null');
    }

    let task = {};

    task.family = config.get('task.name');
    task.networkMode = config.get('task.networkMode');

    let container = {};
    container.name = config.get('task.container.name');
    container.image = imageUri;
    if (config.get('task.container.cpu')) {
        container.cpu = config.get('task.container.cpu');
    }
    if (config.get('task.container.memory')) {
        container.memory = config.get('task.container.memory');
    }
    if (config.get('task.container.memoryReservation')) {
        container.memoryReservation = config.get('task.container.memoryReservation');
    }
    container.portMappings = _.map(config.get('task.container.ports'), (port) => {
        let def = {};
        if (_.isString(port)) {
            def.containerPort = parseInt(port, 10);
        } else if (_.isNumber(port)) {
            def.containerPort = port;
        } else {
            if (!port.container) { throw new TypeError('port definition must specify container port'); }

            def.containerPort = port.container;
            if (port.host) {
                def.hostPort = port.host;
            }
        }

        if (port.protocol) {
            def.protocol = port.protocol;
        } else {
            def.protocol = 'tcp';
        }

        return def;
    });

    container.environment = _.map(config.get('task.container.environment'), (value, key) => {
        return {
            name: key,
            value
        };
    });

    // Validate the container definition
    if (!container.memory && !container.memoryReservation) {
        throw new TypeError('task container must specify memory and/or memoryReservation');
    }

    if (container.memory < container.memoryReservation) {
        throw new TypeError('task container memory must be greater than memoryReservation');
    }

    task.containerDefinitions = [container];

    return Promise.resolve(task);
}

export function ensureClusterExists() {
    let regions = getRegions();
    let cluster = config.get('cluster');

    console.log(chalk.dim(`ensuring cluster ${cluster} exists in ${regions.join(', ')}`));

    return Promise.all(_.map(regions, (region) => {
        let ecs = getECS(region);

        return ecs.describeClusters({
            clusters: [cluster]
        }).promise()
        .then((result) => {
            if (result.clusters.length > 0 && result.clusters[0].status === 'ACTIVE') {
                // Cluster was found, we can just return
                console.log(`    ${chalk.bold.green('\u2713')} cluster ${cluster} found in ${region}`);
                return;
            }

            console.log(chalk.dim(`creating cluster ${cluster} in ${region}`));
            return ecs.createCluster({
                clusterName: cluster
            }).promise()
            .then((result) => {
                console.log(`    ${chalk.bold.green('\u2713')} cluster ${result.cluster.clusterName} created in ${region}`);
            });
        });
    }))
    .then(() => { console.log(); });
}

export function runService(taskDefinition, region) {
    let cluster = config.get('cluster');
    let service = config.get('service');

    console.log(chalk.dim(`starting service ${service.name} for cluster ${cluster} in ${region}`));

    let ecs = getECS(region);

    console.log(chalk.dim(`ensuring service exists in ${region}`));
    return ecs.describeServices({
        services: [service.name],
        cluster
    }).promise()
    .then((result) => {
        if (result.services.length > 0 && result.services[0].status === 'ACTIVE') {
            // Service was found, we can update it
            return updateService(taskDefinition, region);
        }

        return createService(taskDefinition, region);
    })
    .then(({service}) => {
        return {
            service,
            region
        };
    });
}

export function registerTask(task) {
    let regions = getRegions();

    console.log(chalk.dim(`registering task definition in ${regions.join(', ')}`));

    return Promise.all(_.map(regions, (region) => {
        let ecs = getECS(region);

        return ecs.registerTaskDefinition(task).promise()
        .then((result) => {
            let arn = result.taskDefinition.taskDefinitionArn;
            let family = task.family;
            let revision = arn.substring(arn.lastIndexOf(':') + 1);
            console.log(`    ${chalk.bold.green('\u2713')} task ${family}:${revision} created in ${region}`);

            return {
                region,
                task: result.taskDefinition.taskDefinitionArn
            };
        });
    }))
    .then((tasks) => {
        console.log();
        return tasks;
    });
}

export function waitForStable(service, region) {
    let ecs = getECS(region);

    return ecs.waitFor('servicesStable', {
        services: [service.serviceName],
        cluster: config.get('cluster')
    }).promise()
    .then((result) => {
        console.log(`    ${chalk.bold.green('\u2713')} service ${service.serviceName} ${chalk.bold.green('STABLE')} in ${region}`);
        return result;
    });
}
<|endoftext|>


<commit_before>import {pick, omit} from 'lodash'
import shallowequal from 'shallowequal'

/**
 * [mapStateToProps method type description]
 * (a -> b -> b) -> (a -> b -> b)
 */
export function mapStateToProps (propsMapper) {
  return function mapStateToPropsMethod (state, props) {
    return {...props, ...propsMapper(state, props)}
  }
}

// alias of mapStateToProps
export const mapProps = mapStateToProps

/**
 * [mapPropsOnChange method type description]
 * [k] -> (a -> b -> b) -> (a -> b -> b)
 */
export function mapPropsOnChange (dependentPropKeys, propsMapper) {
  let prevProps, computedProps
  return function mapPropsOnChangeMethod (state, props) {
    if (!computedProps) {
      prevProps = props
      computedProps = propsMapper(state, props)
    } else {
      const pickDependentProps = (props) => pick(props, dependentPropKeys)
      if (!shallowequal(
        pickDependentProps(prevProps),
        pickDependentProps(props)
      )) {
        computedProps = propsMapper(state, props)
        prevProps = props
      }
    }
    return {...omit(props, dependentPropKeys), ...computedProps}
  }
}

export function hasObjectTypeError (types, obj, viewModelName = 'hasObjectTypeError Checker') {
  // Always perform checks when running on react native, and short circuit if checks fail
  if ((typeof navigator !== 'undefined' && navigator.product === 'ReactNative') ||
  (typeof process === 'undefined' || process.env.NODE_ENV !== 'production')) {
    const keys = Object.keys(types)
    for (let i in keys) {
      const key = keys[i]
      const message = types[key](obj, key, viewModelName)
      if (message) {
        console.warn(message)
        return true
      }
    }
  }
  return false
}

/**
 * [setPropTypes method type description]
 * (c -> d) -> (a -> b -> b)
 */
export function setPropTypes (propTypes, viewModelName = 'setPropTypes Checker') {
  return function setPropTypesMethod (state, props) {
    // return null if checker found errors
    return hasObjectTypeError(propTypes, props, viewModelName) ? null : props
  }
}

/**
 * [setStateTypes method type description]
 * (c -> d) -> (a -> b -> b)
 */
export function setStateTypes (stateTypes, viewModelName = 'setStateTypes Checker') {
  return function setStateTypesMethod (state, props) {
    return hasObjectTypeError(stateTypes, state, viewModelName) ? null : props
  }
}

/**
 * [composeProps method type description]
 * [(a -> b -> b)] -> (a -> b -> b)
 */
export function composeProps (...funcs) {
  return function composePropsMethod (state, props) {
    props = props || {}
    return funcs.reduce((accProps, func) => {
      // Short circuit if accProps are null, React Native helper
      if (accProps === null) return null
      return func(state, accProps)
    }, props)
  }
}
<commit_msg>run all object type checks even if one fails<commit_after>import {pick, omit} from 'lodash'
import shallowequal from 'shallowequal'

/**
 * [mapStateToProps method type description]
 * (a -> b -> b) -> (a -> b -> b)
 */
export function mapStateToProps (propsMapper) {
  return function mapStateToPropsMethod (state, props) {
    return {...props, ...propsMapper(state, props)}
  }
}

// alias of mapStateToProps
export const mapProps = mapStateToProps

/**
 * [mapPropsOnChange method type description]
 * [k] -> (a -> b -> b) -> (a -> b -> b)
 */
export function mapPropsOnChange (dependentPropKeys, propsMapper) {
  let prevProps, computedProps
  return function mapPropsOnChangeMethod (state, props) {
    if (!computedProps) {
      prevProps = props
      computedProps = propsMapper(state, props)
    } else {
      const pickDependentProps = (props) => pick(props, dependentPropKeys)
      if (!shallowequal(
        pickDependentProps(prevProps),
        pickDependentProps(props)
      )) {
        computedProps = propsMapper(state, props)
        prevProps = props
      }
    }
    return {...omit(props, dependentPropKeys), ...computedProps}
  }
}

export function hasObjectTypeError (types, obj, viewModelName = 'hasObjectTypeError Checker') {
  // Always perform checks when running on react native
  if ((typeof navigator !== 'undefined' && navigator.product === 'ReactNative') ||
  (typeof process === 'undefined' || process.env.NODE_ENV !== 'production')) {
    return Object.keys(types).reduce((acc, key) => {
      const message = types[key](obj, key, viewModelName)
      if (message) {
        console.warn(message)
        return true
      }
      return acc || false
    }, false)
  }
  return false
}

/**
 * [setPropTypes method type description]
 * (c -> d) -> (a -> b -> b)
 */
export function setPropTypes (propTypes, viewModelName = 'setPropTypes Checker') {
  return function setPropTypesMethod (state, props) {
    // return null if checker found errors
    return hasObjectTypeError(propTypes, props, viewModelName) ? null : props
  }
}

/**
 * [setStateTypes method type description]
 * (c -> d) -> (a -> b -> b)
 */
export function setStateTypes (stateTypes, viewModelName = 'setStateTypes Checker') {
  return function setStateTypesMethod (state, props) {
    return hasObjectTypeError(stateTypes, state, viewModelName) ? null : props
  }
}

/**
 * [composeProps method type description]
 * [(a -> b -> b)] -> (a -> b -> b)
 */
export function composeProps (...funcs) {
  return function composePropsMethod (state, props) {
    props = props || {}
    return funcs.reduce((accProps, func) => {
      // Short circuit if accProps are null, React Native helper
      if (accProps === null) return null
      return func(state, accProps)
    }, props)
  }
}
<|endoftext|>


<commit_before><commit_msg>add bootstrapSwitch<commit_after>require('../../vendors/bootstrap-switch/dist/js/bootstrap-switch.min.js');<|endoftext|>


<commit_before>/* global jQuery */
'use strict';

var _logger = require('../logger/logger');
var _cli = require('../utils/cli');

exports.create = function() {
    var _page        = require('webpage').create();

    _page.is_loading = false;

    _page.customHeaders = {
        'Accept-Language': 'en-US'
    };

    /**
     * PhantomJS page settings.
     * See: http://phantomjs.org/api/webpage/property/settings.html
     */
    _page.set = function(name, value) {
        _page.settings[name] = value;
    };

    /**
     * Page load finished
     */
    _page.onLoadFinished = function pageLoadFinished() {
        _page.is_loading = false;
        setupPage();
    };

    /**
     * Page load started
     */
    _page.onLoadStarted = function pageLoadStarted() {
        _page.is_loading = true;
        _page.scrollPosition = {
            top: 0,
            left: 0
        };
    };

    /**
     * Clear localStorage before pages are loaded
     */
    _page.onInitialized = function initialized() {
        _page.evaluate(function() {
            window.localStorage.clear();
        });
    };

    /**
     * Log in-page errors to the command line
     */
    _page.onError = function pageError(msg, args) {
        if (!_cli.debug || !arguments.length) return;
        _logger.error('Error on page: ' + msg);
        for (var i = 0; args && i < args.length; i++) {
            //_logger.error(' - ', args[i]);
            _logger.dir(args[i]);
        }
    };

    /**
     * Log in-page console calls to the command line
     */
    _page.onConsoleMessage = function pageConsoleMessage(message) {
        if (_cli.debug) {
            _logger.comment('  // ', message);
        }
    };

     _page.onUrlChanged = function(targetUrl) {
         if (_cli.debug) {
             _logger.comment('  ↳ ', targetUrl);
         }
     };

    _page.getURL = function() {
        return _page.evaluate(function() {
            return location.href;
        });
    };

    /**
     * Adds .png to a screendump filename if it's not already there
     */
    _page.getDumpName = function(name) {
        if (!(/\.png$/.test(name))) {
            return name + '.png';
        }

        return name;
    };

    /**
     * Dumps the current viewport to .png
     */
    _page.dump = function(title, boundaries, action_data) {
        _page.clipRect = boundaries ? boundaries : {
            top: _page.scrollPosition.top,
            left: _page.scrollPosition.left,
            width: _page.viewportSize.width,
            height: _page.viewportSize.height
        };

        title = _page.getDumpName(title);

        if (action_data) {
            _page.displayActionData(action_data);
        }

        _page.render(title);
        _page.hideActionData();
    };

    /**
     * Creates a
 with the action data for use in screendumps
     */
    _page.displayActionData = function(action_data) {
        if (!_cli.debug) return;

        _page.evaluate(function(action_data) {
            var $action_data = jQuery('
');
            // Needed because https://github.com/ariya/phantomjs/issues/10619
            var top = jQuery(window).scrollTop() + jQuery(window).height() - 16;
            $action_data.css({
                background: 'black',
                color: 'white',
                opacity: 0.75,
                font: '14px/16px monospace',
                position: 'fixed',
                right: 0,
                top: top,
                zIndex: 1000
            });
            // \xa0 is a non-breaking space
            $action_data.text(action_data.parts.join('\xa0\xa0\xa0\xa0'));
            $action_data.prependTo('body');
        }, action_data);
    };

    /**
     * Creates a
 with the action data for use in screendumps
     */
    _page.hideActionData = function() {
        _page.evaluate(function() {
            jQuery('#scout_action_data').remove();
        });
    };

    /**
     * Check if jQuery is loaded on the page, if not: load it
     * Then load the Scout jQuery assertions and utilities
     */
    function setupPage() {
        var has_jquery = _page.evaluate(function() {
            try {
                jQuery.isFunction(jQuery);
                return true;
            } catch (ex) {
                return false;
            }
        });

        if (!has_jquery) {
            if (!_page.injectJs('../node_modules/jquery/dist/jquery.js')) {
                if (!_page.injectJs('../../../node_modules/jquery/dist/jquery.js')) {
                    _logger.error('Unable to locate jQuery. Did you run npm install?');
                    phantom.exit(1);
                }
            }

            _page.evaluate(function() {
                jQuery.noConflict();
            });
        }

        _page.injectJs('./context/client.js');

        // PhantomJS default bg color is transparent
        // This makes for strange screenshots
        _page.evaluate(function() {
            document.body.bgColor = 'white';
        });
    }

    return _page;
};
<commit_msg>Removed leading whitespace<commit_after>/* global jQuery */
'use strict';

var _logger = require('../logger/logger');
var _cli = require('../utils/cli');

exports.create = function() {
    var _page        = require('webpage').create();

    _page.is_loading = false;

    _page.customHeaders = {
        'Accept-Language': 'en-US'
    };

    /**
     * PhantomJS page settings.
     * See: http://phantomjs.org/api/webpage/property/settings.html
     */
    _page.set = function(name, value) {
        _page.settings[name] = value;
    };

    /**
     * Page load finished
     */
    _page.onLoadFinished = function pageLoadFinished() {
        _page.is_loading = false;
        setupPage();
    };

    /**
     * Page load started
     */
    _page.onLoadStarted = function pageLoadStarted() {
        _page.is_loading = true;
        _page.scrollPosition = {
            top: 0,
            left: 0
        };
    };

    /**
     * Clear localStorage before pages are loaded
     */
    _page.onInitialized = function initialized() {
        _page.evaluate(function() {
            window.localStorage.clear();
        });
    };

    /**
     * Log in-page errors to the command line
     */
    _page.onError = function pageError(msg, args) {
        if (!_cli.debug || !arguments.length) return;
        _logger.error('Error on page: ' + msg);
        for (var i = 0; args && i < args.length; i++) {
            //_logger.error(' - ', args[i]);
            _logger.dir(args[i]);
        }
    };

    /**
     * Log in-page console calls to the command line
     */
    _page.onConsoleMessage = function pageConsoleMessage(message) {
        if (_cli.debug) {
            _logger.comment('  // ', message);
        }
    };

    _page.onUrlChanged = function(targetUrl) {
         if (_cli.debug) {
             _logger.comment('  ↳ ', targetUrl);
         }
     };

    _page.getURL = function() {
        return _page.evaluate(function() {
            return location.href;
        });
    };

    /**
     * Adds .png to a screendump filename if it's not already there
     */
    _page.getDumpName = function(name) {
        if (!(/\.png$/.test(name))) {
            return name + '.png';
        }

        return name;
    };

    /**
     * Dumps the current viewport to .png
     */
    _page.dump = function(title, boundaries, action_data) {
        _page.clipRect = boundaries ? boundaries : {
            top: _page.scrollPosition.top,
            left: _page.scrollPosition.left,
            width: _page.viewportSize.width,
            height: _page.viewportSize.height
        };

        title = _page.getDumpName(title);

        if (action_data) {
            _page.displayActionData(action_data);
        }

        _page.render(title);
        _page.hideActionData();
    };

    /**
     * Creates a
 with the action data for use in screendumps
     */
    _page.displayActionData = function(action_data) {
        if (!_cli.debug) return;

        _page.evaluate(function(action_data) {
            var $action_data = jQuery('
');
            // Needed because https://github.com/ariya/phantomjs/issues/10619
            var top = jQuery(window).scrollTop() + jQuery(window).height() - 16;
            $action_data.css({
                background: 'black',
                color: 'white',
                opacity: 0.75,
                font: '14px/16px monospace',
                position: 'fixed',
                right: 0,
                top: top,
                zIndex: 1000
            });
            // \xa0 is a non-breaking space
            $action_data.text(action_data.parts.join('\xa0\xa0\xa0\xa0'));
            $action_data.prependTo('body');
        }, action_data);
    };

    /**
     * Creates a
 with the action data for use in screendumps
     */
    _page.hideActionData = function() {
        _page.evaluate(function() {
            jQuery('#scout_action_data').remove();
        });
    };

    /**
     * Check if jQuery is loaded on the page, if not: load it
     * Then load the Scout jQuery assertions and utilities
     */
    function setupPage() {
        var has_jquery = _page.evaluate(function() {
            try {
                jQuery.isFunction(jQuery);
                return true;
            } catch (ex) {
                return false;
            }
        });

        if (!has_jquery) {
            if (!_page.injectJs('../node_modules/jquery/dist/jquery.js')) {
                if (!_page.injectJs('../../../node_modules/jquery/dist/jquery.js')) {
                    _logger.error('Unable to locate jQuery. Did you run npm install?');
                    phantom.exit(1);
                }
            }

            _page.evaluate(function() {
                jQuery.noConflict();
            });
        }

        _page.injectJs('./context/client.js');

        // PhantomJS default bg color is transparent
        // This makes for strange screenshots
        _page.evaluate(function() {
            document.body.bgColor = 'white';
        });
    }

    return _page;
};
<|endoftext|>


<commit_before>import Immutable, { Map } from 'immutable';
import webApi from './web_api';
import { getEntity, read, removeEntity, swap, setEntity, updateEntity } from '../store/index';
import { syncRemoteData } from './remote_data';
import * as l from './index';
import { img as preload } from '../utils/preload_utils';
import { defaultProps } from '../ui/box/container';
import { isFieldValid, showInvalidField } from '../field/index';

export function setupLock(id, clientID, domain, options, logInCallback, hookRunner, emitEventFn) {
  let m = syncRemoteData(l.setup(id, clientID, domain, options, logInCallback, hookRunner, emitEventFn));
  preload(l.ui.logo(m) || defaultProps.logo);

  webApi.setupClient(id, clientID, domain, l.withAuthOptions(m, {
    ...options,
    popupOptions: l.ui.popupOptions(m)
  }));

  m = l.runHook(m, "didInitialize", options);

  swap(setEntity, "lock", id, m);

  if (l.auth.redirect(m)) {
    const hash = webApi.parseHash(id);
    // TODO: this leaves the hash symbol (#) in the URL, maybe we can
    // use the history API instead to remove it.
    global.location.hash = "";

    let error, result;

    if (hash) {
      if (hash.error) {
        error = hash;
      } else {
        result = hash;
      }
    }

    setTimeout(() => l.invokeLogInCallback(m, error, result), 0);
  }

}

export function openLock(id) {
  const m = read(getEntity, "lock", id);
  if (!m) {
    throw new Error("The Lock can't be opened again after it has been destroyed");
  }

  if (l.rendering(m)) {
    return false;
  }

  l.emitEvent(m, "show");

  swap(updateEntity, "lock", id, l.render);

  return true;
}

export function closeLock(id, force = false, callback = () => {}) {
  // Do nothing when the Lock can't be closed, unless closing is forced.
  let lock = read(getEntity, "lock", id);
  if (!l.ui.closable(lock) && !force) {
    return;
  }

  // If it is a modal, stop rendering an reset after a second,
  // otherwise just reset.
  if (l.ui.appendContainer(lock)) {
    swap(updateEntity, "lock", id, l.stopRendering);

    setTimeout(() => {
      swap(updateEntity, "lock", id, l.reset);
      callback(read(getEntity, "lock", id));
    }, 1000);
  } else {
    swap(updateEntity, "lock", id, l.reset);
    callback(lock);
  }
}

export function removeLock(id) {
  swap(updateEntity, "lock", id, l.stopRendering);
  swap(removeEntity, "lock", id);
}

export function updateLock(id, f) {
  return swap(updateEntity, "lock", id, f);
}

export function pinLoadingPane(id) {
  const lock = read(getEntity, "lock", id);
  if (!lock.get("isLoadingPanePinned")) {
    swap(updateEntity, "lock", id, m => m.set("isLoadingPanePinned", true));
  }
}

export function unpinLoadingPane(id) {
  swap(updateEntity, "lock", id, m => m.set("isLoadingPanePinned", false));
}

function emitEvent(id, str, ...args) {
  l.emitEvent(read(getEntity, "lock", id), str, ...args);
}

export function validateAndSubmit(id, fields = [], f) {
  swap(updateEntity, "lock", id, m => {
    const allFieldsValid = fields.reduce((r, x) => r && isFieldValid(m, x), true);
    return allFieldsValid
      ? l.setSubmitting(m, true)
      : fields.reduce((r, x) => showInvalidField(r, x), m);
  });

  const m = read(getEntity, "lock", id);
  if (l.submitting(m)) {
    f(m);
  }
}

export function logIn(id, fields, params = {}) {
  validateAndSubmit(id, fields, m => {
    webApi.logIn(id, params, (error, ...args) => {
      if (error) {
        setTimeout(() => logInError(id, fields, error), 250);
      } else {
        logInSuccess(id, ...args);
      }
    });
  });
}

export function logInSuccess(id, ...args) {
  const m = read(getEntity, "lock", id);

  if (!l.ui.autoclose(m)) {
    swap(updateEntity, "lock", id, m => {
      m = l.setSubmitting(m, false);
      return l.setLoggedIn(m, true);
    });

    l.invokeLogInCallback(m, null, ...args);
  } else {
    closeLock(id, false, m1 => l.invokeLogInCallback(m1, null, ...args));
  }
}

function logInError(id, fields, error) {
  const m = read(getEntity, "lock", id);
  const errorMessage = l.loginErrorMessage(m, error, loginType(fields));

  swap(updateEntity, "lock", id, l.setSubmitting, false, errorMessage);
}

function loginType(fields) {
  if (!fields) return;
  if (~fields.indexOf("vcode")) return "code";
  if (~fields.indexOf("username")) return "username";
  if (~fields.indexOf("email")) return "email";
}
<commit_msg>Emit "hide" event<commit_after>import Immutable, { Map } from 'immutable';
import webApi from './web_api';
import { getEntity, read, removeEntity, swap, setEntity, updateEntity } from '../store/index';
import { syncRemoteData } from './remote_data';
import * as l from './index';
import { img as preload } from '../utils/preload_utils';
import { defaultProps } from '../ui/box/container';
import { isFieldValid, showInvalidField } from '../field/index';

export function setupLock(id, clientID, domain, options, logInCallback, hookRunner, emitEventFn) {
  let m = syncRemoteData(l.setup(id, clientID, domain, options, logInCallback, hookRunner, emitEventFn));
  preload(l.ui.logo(m) || defaultProps.logo);

  webApi.setupClient(id, clientID, domain, l.withAuthOptions(m, {
    ...options,
    popupOptions: l.ui.popupOptions(m)
  }));

  m = l.runHook(m, "didInitialize", options);

  swap(setEntity, "lock", id, m);

  if (l.auth.redirect(m)) {
    const hash = webApi.parseHash(id);
    // TODO: this leaves the hash symbol (#) in the URL, maybe we can
    // use the history API instead to remove it.
    global.location.hash = "";

    let error, result;

    if (hash) {
      if (hash.error) {
        error = hash;
      } else {
        result = hash;
      }
    }

    setTimeout(() => l.invokeLogInCallback(m, error, result), 0);
  }

}

export function openLock(id) {
  const m = read(getEntity, "lock", id);
  if (!m) {
    throw new Error("The Lock can't be opened again after it has been destroyed");
  }

  if (l.rendering(m)) {
    return false;
  }

  l.emitEvent(m, "show");

  swap(updateEntity, "lock", id, l.render);

  return true;
}

export function closeLock(id, force = false, callback = () => {}) {
  // Do nothing when the Lock can't be closed, unless closing is forced.
  let m = read(getEntity, "lock", id);
  if (!l.ui.closable(m) && !force) {
    return;
  }

  l.emitEvent(m, "hide")

  // If it is a modal, stop rendering an reset after a second,
  // otherwise just reset.
  if (l.ui.appendContainer(m)) {
    swap(updateEntity, "lock", id, l.stopRendering);

    setTimeout(() => {
      swap(updateEntity, "lock", id, l.reset);
      m = read(getEntity, "lock", id);
      callback(m);
    }, 1000);
  } else {
    swap(updateEntity, "lock", id, l.reset);
    callback(m);
  }
}

export function removeLock(id) {
  swap(updateEntity, "lock", id, l.stopRendering);
  swap(removeEntity, "lock", id);
}

export function updateLock(id, f) {
  return swap(updateEntity, "lock", id, f);
}

export function pinLoadingPane(id) {
  const lock = read(getEntity, "lock", id);
  if (!lock.get("isLoadingPanePinned")) {
    swap(updateEntity, "lock", id, m => m.set("isLoadingPanePinned", true));
  }
}

export function unpinLoadingPane(id) {
  swap(updateEntity, "lock", id, m => m.set("isLoadingPanePinned", false));
}

function emitEvent(id, str, ...args) {
  l.emitEvent(read(getEntity, "lock", id), str, ...args);
}

export function validateAndSubmit(id, fields = [], f) {
  swap(updateEntity, "lock", id, m => {
    const allFieldsValid = fields.reduce((r, x) => r && isFieldValid(m, x), true);
    return allFieldsValid
      ? l.setSubmitting(m, true)
      : fields.reduce((r, x) => showInvalidField(r, x), m);
  });

  const m = read(getEntity, "lock", id);
  if (l.submitting(m)) {
    f(m);
  }
}

export function logIn(id, fields, params = {}) {
  validateAndSubmit(id, fields, m => {
    webApi.logIn(id, params, (error, ...args) => {
      if (error) {
        setTimeout(() => logInError(id, fields, error), 250);
      } else {
        logInSuccess(id, ...args);
      }
    });
  });
}

export function logInSuccess(id, ...args) {
  const m = read(getEntity, "lock", id);

  if (!l.ui.autoclose(m)) {
    swap(updateEntity, "lock", id, m => {
      m = l.setSubmitting(m, false);
      return l.setLoggedIn(m, true);
    });

    l.invokeLogInCallback(m, null, ...args);
  } else {
    closeLock(id, false, m1 => l.invokeLogInCallback(m1, null, ...args));
  }
}

function logInError(id, fields, error) {
  const m = read(getEntity, "lock", id);
  const errorMessage = l.loginErrorMessage(m, error, loginType(fields));

  swap(updateEntity, "lock", id, l.setSubmitting, false, errorMessage);
}

function loginType(fields) {
  if (!fields) return;
  if (~fields.indexOf("vcode")) return "code";
  if (~fields.indexOf("username")) return "username";
  if (~fields.indexOf("email")) return "email";
}
<|endoftext|>


<commit_before>import isError from 'lodash/isError'
import isFunction from 'lodash/isFunction'
import isObject from 'lodash/isObject'
import isUndefined from 'lodash/isUndefined'
import pickBy from 'lodash/pickBy'

export function payloadCreatorDefault(payload) {
  if (isError(payload) || isObject(payload)) {
    return pickBy(payload, (val) => !isUndefined(val) && !isFunction(val))
  }
  return payload
}
export default function createAction(type, payloadCreator, metaCreator) {
  const getPayload = isFunction(payloadCreator) ? payloadCreator : payloadCreatorDefault
  return (...args) => {
    const action = { type }
    const payload = getPayload(...args)
    if (!isUndefined(payload)) action.payload = payload
    // Handle FSA errors where the payload is an Error object or has error prop. Set error.
    if (args.length === 1 && (isError(args[0]) || args[0].error)) {
      action.error = true
    }
    if (isFunction(metaCreator)) {
      action.meta = metaCreator(...args)
    }
    return action
  }
}
<commit_msg>Boom errors<commit_after>import isError from 'lodash/isError'
import isFunction from 'lodash/isFunction'
import isObject from 'lodash/isObject'
import isUndefined from 'lodash/isUndefined'
import pickBy from 'lodash/pickBy'

export function payloadCreatorDefault(payload) {
  if (isError(payload) || isObject(payload)) {
    return pickBy(payload, (val) => !isUndefined(val) && !isFunction(val))
  }
  return payload
}
export default function createAction(type, payloadCreator, metaCreator) {
  const getPayload = isFunction(payloadCreator) ? payloadCreator : payloadCreatorDefault
  return (...args) => {
    const action = { type }
    const payload = getPayload(...args)
    if (!isUndefined(payload)) action.payload = payload
    // Handle FSA errors where the payload is an Error object or has error prop. Set error.
    if (isError(args[0]) || args[0].error || args[0].isBoom) {
      action.error = true
    }
    if (isFunction(metaCreator)) {
      action.meta = metaCreator(...args)
    }
    return action
  }
}
<|endoftext|>


<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is JavaScript Deobfuscator.
 *
 * The Initial Developer of the Original Code is
 * Wladimir Palant.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

const debuggerService = Components.classes["@mozilla.org/js/jsd/debugger-service;1"]
                                  .getService(Components.interfaces.jsdIDebuggerService);
const ioService = Components.classes["@mozilla.org/network/io-service;1"]
                            .getService(Components.interfaces.nsIIOService);
var appDir, profDir;
var executedScripts = {__proto__: null};
var debuggerWasOn = false;
var debuggerOldFlags;
var filters = {include: [], exclude: []};

var paused = false;

function start()
{
  document.getElementById("tabs").addEventListener("select", function(event)
  {
    if (event.target.localName != "tabs")
      return;

    closeFindbar();

    setTimeout(function()
    {
      // Move focus away from tabs when tab selection is switched (idea stolen from dialog.xml)
      let focusedElement = document.commandDispatcher.focusedElement;
      if (focusedElement && focusedElement.localName == "tab")
        document.commandDispatcher.advanceFocusIntoSubtree(focusedElement);
    }, 0);
  }, false)

  // Initialize frames with data: URLs to prevent them from getting chrome privileges
  let request = new XMLHttpRequest();
  request.open("GET", "chrome://jsdeobfuscator/content/scriptList.xhtml", false);
  request.send(null);
  let scriptListURL = "data:text/xml," + encodeURIComponent(request.responseText);
  for each (let frameId in ["compiled-frame", "executed-frame"])
  {
    let frame = document.getElementById(frameId);
    frame.docShell.allowAuth = false;
    frame.docShell.allowImages = false;
    frame.docShell.allowJavascript = false;
    frame.docShell.allowMetaRedirects = false;
    frame.docShell.allowPlugins = false;
    frame.docShell.allowSubframes = false;
    frame.webNavigation.loadURI(scriptListURL, 0, null, null, null);
  }

  // Determine location of profile and application directory (scripts located there shouldn't be shown)
  let ioServ = Components.classes["@mozilla.org/network/io-service;1"]
                         .getService(Components.interfaces.nsIIOService);
  let dirServ = Components.classes["@mozilla.org/file/directory_service;1"]
                          .getService(Components.interfaces.nsIProperties);
  function getDirURL(key)
  {
    try
    {
      let file = dirServ.get(key, Components.interfaces.nsIFile);
      return ioServ.newFileURI(file).spec.toLowerCase().replace(/\/+/g, "/");
    }
    catch (e)
    {
      return null;
    }
  }
  appDir = getDirURL("GreD");
  profDir = getDirURL("ProfD");

  updateFiltersUI();

  // Initialize debugger
  debuggerWasOn = debuggerService.isOn;
  if (!debuggerWasOn)
    debuggerService.on();

  debuggerService.scriptHook = scriptHook;
  debuggerService.functionHook = scriptHook;
  debuggerService.topLevelHook = scriptHook;

  debuggerOldFlags = debuggerService.flags;
  debuggerService.flags = debuggerOldFlags | Components.interfaces.jsdIDebuggerService.DISABLE_OBJECT_TRACE;
}

function stop()
{
  debuggerService.scriptHook = null;
  debuggerService.functionHook = null;
  debuggerService.topLevelHook = null;
  debuggerService.interruptHook = null;
  debuggerService.flags = debuggerOldFlags;
  if (!debuggerWasOn)
    debuggerService.off();
}

function updateFiltersUI()
{
  // Read out JSON preference
  try
  {
    let prefService = Components.classes["@mozilla.org/preferences-service;1"]
                                .getService(Components.interfaces.nsIPrefBranch);
    filters = Components.classes["@mozilla.org/dom/json;1"]
                         .getService(Components.interfaces.nsIJSON)
                         .decode(prefService.getCharPref("extensions.jsdeobfuscator.filters"));
  } catch(e) { return; };

  for each (let type in ["include", "exclude"])
  {
    let element = document.getElementById(type + "Filters");
    if (filters[type].length)
      element.textContent = filters[type].join(", ");
    else
      element.textContent = element.getAttribute("defValue");
  }
}

function checkMatch(fileName, filters)
{
  fileName = fileName.toLowerCase().replace(/\/+/g, "/");
  for each (let filter in filters)
  {
    if (appDir)
      filter = filter.replace(/%APPDIR%/gi, appDir);
    if (profDir)
      filter = filter.replace(/%PROFILEDIR%/gi, profDir);
    filter = filter.toLowerCase().replace(/\/+/g, "/");

    if (fileName.indexOf(filter) == 0)
      return true;
  }
  return false;
}

function addScript(action, script)
{
  if (paused)
    return;

  // Check filters first
  if (filters.include.length && !checkMatch(script.fileName, filters.include))
    return;
  if (checkMatch(script.fileName, filters.exclude))
    return;

  // Don't show script execution twice
  if (action == "executed" && script.tag in executedScripts)
  {
    updateExecutedScript(script, false);
    return;
  }

  let fileURI = script.fileName;
  try
  {
    // Debugger service messes up file:/ URLs, try to fix them
    fileURI = ioService.newURI(fileURI, null, null).spec;
  } catch(e) {}

  let frame = document.getElementById(action + "-frame");
  let needScroll = (frame.contentWindow.scrollY >= frame.contentWindow.scrollMaxY - 10);

  let doc = document.getElementById(action + "-frame").contentDocument;

  let template = doc.getElementById("template");
  let entry = template.cloneNode(true);
  entry.removeAttribute("id");
  entry.getElementsByClassName("time")[0].textContent = getTime();
  entry.getElementsByClassName("scriptLine")[0].textContent = script.baseLineNumber;
  entry.getElementsByClassName("scriptText")[0].textContent = script.functionSource;

  let scriptURLNode = entry.getElementsByClassName("scriptURL")[0];
  scriptURLNode.href = scriptURLNode.textContent = fileURI;
  scriptURLNode.lineNum = script.baseLineNumber;

  template.parentNode.appendChild(entry);

  if (action == "executed")
  {
    executedScripts[script.tag] = {
      entry: entry,
      startTime: Date.now(),
      calls: 1,
      returns: 0,
      executionTime: 0
    };
  }

  if (needScroll)
    frame.contentWindow.scrollTo(frame.contentWindow.scrollX, frame.contentWindow.scrollMaxY);
}

function updateExecutedScript(script, isReturn)
{
  let scriptData = executedScripts[script.tag];
  if (!scriptData)
    return;

  if (isReturn)
  {
    if (scriptData.startTime)
    {
      scriptData.returns++;
      if (typeof scriptData.executionTime != "undefined")
        scriptData.executionTime += Date.now() - scriptData.startTime;
      scriptData.startTime = 0;
    }
  }
  else
  {
    if (typeof scriptData.executionTime != "undefined")
    {
      if (scriptData.calls != scriptData.returns)
        scriptData.executionTime = undefined;
      else
        scriptData.startTime = Date.now();
    }
    scriptData.calls++;
  }

  if (scriptData.returns > 0)
  {
    let entry = scriptData.entry;
    let wnd = entry.ownerDocument.defaultView;
    let needScroll = (wnd.scrollY >= wnd.scrollMaxY - 10);

    entry.getElementsByClassName("numCalls")[0].textContent = scriptData.returns;

    let avgTime = entry.getElementsByClassName("avgTime")[0];
    if (typeof scriptData.executionTime != "undefined")
      avgTime.textContent = (scriptData.executionTime / scriptData.returns).toFixed(0);
    else
      avgTime.textContent = avgTime.getAttribute("recursion");

    entry.getElementsByClassName("stats")[0].removeAttribute("style");

    if (needScroll)
      wnd.scrollTo(wnd.scrollX, wnd.scrollMaxY);
  }
}

function clearList()
{
  for each (let frameId in ["compiled-frame", "executed-frame"])
  {
    let dummy = document.getElementById(frameId).contentDocument.getElementById("dummy");
    while (dummy.nextSibling)
      dummy.parentNode.removeChild(dummy.nextSibling);

    executedScripts = {__proto__: null};
  }
}

// HACK: Using a string bundle to format a time. Unfortunately, format() function isn't
// exposed in any other way (bug 451360).
var timeFormat = Components.classes["@mozilla.org/intl/stringbundle;1"]
                           .getService(Components.interfaces.nsIStringBundleService)
                           .createBundle("data:text/plain,format=" + encodeURIComponent("%02S:%02S:%02S.%03S"));
function getTime()
{
  let time = new Date();
  return timeFormat.formatStringFromName("format", [time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()], 4);
}

function openFindbar()
{
  let tabs = document.getElementById("tabs");
  let selectedPanel = (tabs.selectedPanel.id == "compiled-panel" ? "compiled" : "executed");
  let findbar = document.getElementById(selectedPanel + "-findbar");
  findbar.startFind(findbar.FIND_NORMAL);
}

function closeFindbar()
{
  for each (let id in ["compiled-findbar", "executed-findbar"])
    document.getElementById(id).close();
}

function updateContext()
{
  for each (let command in ["copy", "selectAll"])
  {
    let enabled = true;
    try
    {
      let controller = document.commandDispatcher.getControllerForCommand("cmd_" + command);
      enabled = (controller && controller.isCommandEnabled("cmd_" + command));
    }
    catch (e) {}

    document.getElementById("context-" + command).setAttribute("disabled", !enabled);
  }

  let linkNode = document.popupNode;
  while (linkNode && !(linkNode instanceof HTMLAnchorElement))
    linkNode = linkNode.parentNode;
  document.getElementById("context-copyLink").setAttribute("disabled", !linkNode);
}

function execCommand(command)
{
  try
  {
    let controller = document.commandDispatcher.getControllerForCommand(command);
    if (controller && controller.isCommandEnabled(command))
      controller.doCommand(command);
  }
  catch (e) {}
}

function selectAll(anchor)
{
  let doc = anchor.ownerDocument;
  let dummy = doc.getElementById("dummy");
  let selection = doc.defaultView.getSelection();

  // Copy command will copy invisible elements, make sure not to select too much
  let range = document.createRange();
  range.selectNodeContents(dummy.parentNode);
  if (dummy.offsetHeight)
    range.setStartBefore(dummy);
  else
    range.setStartAfter(dummy);
  selection.removeAllRanges();
  selection.addRange(range);
}

function handleBrowserClick(event)
{
  if (event.button != 0)
    return;

  event.preventDefault();

  let linkNode = event.target;
  while (linkNode && !(linkNode instanceof HTMLAnchorElement))
    linkNode = linkNode.parentNode;
  if (!linkNode)
    return;

  // viewSourceUtils.js would help but it isn't unusable enough in Firefox 3.0
  window.openDialog("chrome://global/content/viewSource.xul", "_blank", "all,dialog=no", linkNode.href, null, null, linkNode.lineNum, false);
}

function editFilters()
{
  let result = {};
  window.openDialog("editfilters.xul", "_blank", "modal,centerscreen,resizable", filters, result);
  if ("include" in result)
  {
    // Save preferences
    try
    {
      let prefService = Components.classes["@mozilla.org/preferences-service;1"]
                                  .getService(Components.interfaces.nsIPrefBranch);
      let json = Components.classes["@mozilla.org/dom/json;1"]
                           .getService(Components.interfaces.nsIJSON)
                           .encode(result);
      prefService.setCharPref("extensions.jsdeobfuscator.filters", json);
      prefService.QueryInterface(Components.interfaces.nsIPrefService).savePrefFile(null);
      updateFiltersUI();
    } catch(e) {};
  }
}

function resetFilters()
{
  try
  {
    let prefService = Components.classes["@mozilla.org/preferences-service;1"]
                                .getService(Components.interfaces.nsIPrefBranch);
    prefService.clearUserPref("extensions.jsdeobfuscator.filters");
      updateFiltersUI();
  } catch(e) {};
}

var scriptHook =
{
  onScriptCreated: function(script)
  {
    addScript("compiled", script);
  },
  onScriptDestroyed: function(script)
  {
  },
  onCall: function(frame, type)
  {
    if (type == Components.interfaces.jsdICallHook.TYPE_TOPLEVEL_START || type == Components.interfaces.jsdICallHook.TYPE_FUNCTION_CALL)
      addScript("executed", frame.script);
    else if (type == Components.interfaces.jsdICallHook.TYPE_TOPLEVEL_END || type == Components.interfaces.jsdICallHook.TYPE_FUNCTION_RETURN)
      updateExecutedScript(frame.script, true);
  },
  prevScript: null,
  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.jsdIScriptHook, Components.interfaces.jsdICallHook])
}
<commit_msg>Improved performance by processing incoming data asyncronously every 100 ms, made profiling data more realistic as well. Other changes: * Added Cc/Ci/Cu shortcut constants * Fixed the way application directory was determined (failed for XULRunner-based applications) * Shared services between functions where it made sense * Improved performance of the Clear button * Report caught errors to error console instead of swallowing them silently<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is JavaScript Deobfuscator.
 *
 * The Initial Developer of the Original Code is
 * Wladimir Palant.
 * Portions created by the Initial Developer are Copyright (C) 2009
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");

const debuggerService = Cc["@mozilla.org/js/jsd/debugger-service;1"].getService(Ci.jsdIDebuggerService);
const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
const threadManager = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
const prefService = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
const JSONServ = Cc["@mozilla.org/dom/json;1"].getService(Ci.nsIJSON);

var appDir, profDir;
var executedScripts = {__proto__: null};
var debuggerWasOn = false;
var debuggerOldFlags;
var filters = {include: [], exclude: []};
var queue = null;
var queuedScripts = null;

var paused = false;

function start()
{
  document.getElementById("tabs").addEventListener("select", function(event)
  {
    if (event.target.localName != "tabs")
      return;

    closeFindbar();

    setTimeout(function()
    {
      // Move focus away from tabs when tab selection is switched (idea stolen from dialog.xml)
      let focusedElement = document.commandDispatcher.focusedElement;
      if (focusedElement && focusedElement.localName == "tab")
        document.commandDispatcher.advanceFocusIntoSubtree(focusedElement);
    }, 0);
  }, false)

  // Initialize frames with data: URLs to prevent them from getting chrome privileges
  let request = new XMLHttpRequest();
  request.open("GET", "chrome://jsdeobfuscator/content/scriptList.xhtml", false);
  request.send(null);
  let scriptListURL = "data:text/xml," + encodeURIComponent(request.responseText);
  for each (let frameId in ["compiled-frame", "executed-frame"])
  {
    let frame = document.getElementById(frameId);
    frame.docShell.allowAuth = false;
    frame.docShell.allowImages = false;
    frame.docShell.allowJavascript = false;
    frame.docShell.allowMetaRedirects = false;
    frame.docShell.allowPlugins = false;
    frame.docShell.allowSubframes = false;
    frame.webNavigation.loadURI(scriptListURL, 0, null, null, null);
  }

  // Determine location of profile and application directory (scripts located there shouldn't be shown)
  let dirServ = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
  function getDirURL(key)
  {
    try
    {
      let file = dirServ.get(key, Ci.nsIFile);
      return ioService.newFileURI(file).spec.toLowerCase().replace(/\/+/g, "/");
    }
    catch (e)
    {
      return null;
    }
  }
  appDir = getDirURL("CurProcD");
  profDir = getDirURL("ProfD");

  updateFiltersUI();

  // Initialize debugger
  debuggerWasOn = debuggerService.isOn;
  if (!debuggerWasOn)
    debuggerService.on();

  debuggerService.scriptHook = scriptHook;
  debuggerService.functionHook = scriptHook;
  debuggerService.topLevelHook = scriptHook;

  debuggerOldFlags = debuggerService.flags;
  debuggerService.flags = debuggerOldFlags | Ci.jsdIDebuggerService.DISABLE_OBJECT_TRACE;
}

function stop()
{
  debuggerService.scriptHook = null;
  debuggerService.functionHook = null;
  debuggerService.topLevelHook = null;
  debuggerService.interruptHook = null;
  debuggerService.flags = debuggerOldFlags;
  if (!debuggerWasOn)
    debuggerService.off();
}

function updateFiltersUI()
{
  // Read out JSON preference
  try
  {
    filters = JSONServ.decode(prefService.getCharPref("extensions.jsdeobfuscator.filters"));
  }
  catch(e)
  {
    Components.utils.reportError(e);
    return;
  }

  for each (let type in ["include", "exclude"])
  {
    let element = document.getElementById(type + "Filters");
    if (filters[type].length)
      element.textContent = filters[type].join(", ");
    else
      element.textContent = element.getAttribute("defValue");
  }
}

function checkMatch(fileName, filters)
{
  fileName = fileName.toLowerCase().replace(/\/+/g, "/");
  for each (let filter in filters)
  {
    if (appDir)
      filter = filter.replace(/%APPDIR%/gi, appDir);
    if (profDir)
      filter = filter.replace(/%PROFILEDIR%/gi, profDir);
    filter = filter.toLowerCase().replace(/\/+/g, "/");

    if (fileName.indexOf(filter) == 0)
      return true;
  }
  return false;
}

function processAction(action, script)
{
  if (paused)
    return;

  // For returns accept only known scripts. For other actions check filters.
  if (action == "returned")
  {
    if (!(script.tag in executedScripts) && (!queuedScripts || !(script.tag in queuedScripts)))
      return;
  }
  else
  {
    if (filters.include.length && !checkMatch(script.fileName, filters.include))
      return;
    if (checkMatch(script.fileName, filters.exclude))
      return;
  }

  if (!queue)
  {
    queue = [];
    queuedScripts = {__proto__: null};
    setTimeout(processQueue, 100);
  }

  if (script.tag in queuedScripts)
  {
    queuedScripts[script.tag].actions.push([action, new Date()]);
  }
  else
  {
    // Have to get the source now, top-level scripts will be gone later
    let source = (script.tag in executedScripts ? null : script.functionSource);
    let entry = {script: script, source: source, actions: [[action, new Date()]]};
    queue.push(entry);
    queuedScripts[script.tag] = entry;
  }
}

function processQueue()
{
  let compiledFrame = document.getElementById("compiled-frame").contentWindow;
  let executedFrame = document.getElementById("executed-frame").contentWindow;
  let needScrollCompiled = (compiledFrame.scrollY >= compiledFrame.scrollMaxY - 10);
  let needScrollExecuted = (executedFrame.scrollY >= executedFrame.scrollMaxY - 10);

  let updateNeeded = {__proto__: null};

  let scripts = queue;
  queue = null;
  queuedScripts = null;
  for each (let entry in scripts)
  {
    let script = entry.script;
    for each (let [action, time] in entry.actions)
    {
      switch (action)
      {
        case "compiled":
          addScript(compiledFrame, script, entry.source, time);
          break;
        case "executed":
          // Update existing entry for known scripts
          if (script.tag in executedScripts)
          {
            let scriptData = executedScripts[script.tag];
            if (typeof scriptData.executionTime != "undefined")
            {
              if (scriptData.calls != scriptData.returns)
                scriptData.executionTime = undefined;
              else
                scriptData.startTime = time.getTime();
            }
            scriptData.calls++;
            updateNeeded[script.tag] = scriptData;
          }
          else
          {
            executedScripts[script.tag] = {
              entry: addScript(executedFrame, script, entry.source, time),
              startTime: time.getTime(),
              calls: 1,
              returns: 0,
              executionTime: 0
            };
          }
          break;
        case "returned":
          let scriptData = executedScripts[script.tag];
          if (scriptData.startTime)
          {
            scriptData.returns++;
            if (typeof scriptData.executionTime != "undefined")
              scriptData.executionTime += time.getTime() - scriptData.startTime;
            scriptData.startTime = 0;
            updateNeeded[script.tag] = scriptData;
          }
          break;
      }
    }
  }

  for each (let scriptData in updateNeeded)
    updateExecutedScript(scriptData);

  if (needScrollCompiled)
    compiledFrame.scrollTo(compiledFrame.scrollX, compiledFrame.scrollMaxY);
  if (needScrollExecuted)
    executedFrame.scrollTo(executedFrame.scrollX, executedFrame.scrollMaxY);
}

function addScript(frame, script, source, time)
{
  let fileURI = script.fileName;
  try
  {
    // Debugger service messes up file:/ URLs, try to fix them
    fileURI = ioService.newURI(fileURI, null, null).spec;
  } catch(e) {}

  let doc = frame.document;

  let template = doc.getElementById("template");
  let entry = template.cloneNode(true);
  entry.removeAttribute("id");
  entry.getElementsByClassName("time")[0].textContent = formatTime(time);
  entry.getElementsByClassName("scriptLine")[0].textContent = script.baseLineNumber;
  entry.getElementsByClassName("scriptText")[0].textContent = source;

  let scriptURLNode = entry.getElementsByClassName("scriptURL")[0];
  scriptURLNode.href = scriptURLNode.textContent = fileURI;
  scriptURLNode.lineNum = script.baseLineNumber;

  template.parentNode.appendChild(entry);
  return entry;
}

function updateExecutedScript(scriptData)
{
  if (scriptData.returns > 0)
  {
    let entry = scriptData.entry;
    let wnd = entry.ownerDocument.defaultView;

    entry.getElementsByClassName("numCalls")[0].textContent = scriptData.returns;

    let avgTime = entry.getElementsByClassName("avgTime")[0];
    if (typeof scriptData.executionTime != "undefined")
      avgTime.textContent = (scriptData.executionTime / scriptData.returns).toFixed(0);
    else
      avgTime.textContent = avgTime.getAttribute("recursion");

    entry.getElementsByClassName("stats")[0].removeAttribute("style");
  }
}

function clearList()
{
  for each (let frameId in ["compiled-frame", "executed-frame"])
  {
    let doc = document.getElementById(frameId).contentDocument;
    let dummy = doc.getElementById("dummy");
    let range = doc.createRange();
    range.setStartAfter(dummy);
    range.setEndAfter(dummy.parentNode.lastChild);
    range.deleteContents();
  }
  executedScripts = {__proto__: null};
}

// HACK: Using a string bundle to format a time. Unfortunately, format() function isn't
// exposed in any other way (bug 451360).
var timeFormat = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService)
                           .createBundle("data:text/plain,format=" + encodeURIComponent("%02S:%02S:%02S.%03S"));
function formatTime(time)
{
  return timeFormat.formatStringFromName("format", [time.getHours(), time.getMinutes(), time.getSeconds(), time.getMilliseconds()], 4);
}

function openFindbar()
{
  let tabs = document.getElementById("tabs");
  let selectedPanel = (tabs.selectedPanel.id == "compiled-panel" ? "compiled" : "executed");
  let findbar = document.getElementById(selectedPanel + "-findbar");
  findbar.startFind(findbar.FIND_NORMAL);
}

function closeFindbar()
{
  for each (let id in ["compiled-findbar", "executed-findbar"])
    document.getElementById(id).close();
}

function updateContext()
{
  for each (let command in ["copy", "selectAll"])
  {
    let enabled = true;
    try
    {
      let controller = document.commandDispatcher.getControllerForCommand("cmd_" + command);
      enabled = (controller && controller.isCommandEnabled("cmd_" + command));
    }
    catch(e)
    {
      Components.utils.reportError(e);
    }

    document.getElementById("context-" + command).setAttribute("disabled", !enabled);
  }

  let linkNode = document.popupNode;
  while (linkNode && !(linkNode instanceof HTMLAnchorElement))
    linkNode = linkNode.parentNode;
  document.getElementById("context-copyLink").setAttribute("disabled", !linkNode);
}

function execCommand(command)
{
  try
  {
    let controller = document.commandDispatcher.getControllerForCommand(command);
    if (controller && controller.isCommandEnabled(command))
      controller.doCommand(command);
  }
  catch(e)
  {
    Components.utils.reportError(e);
  }
}

function selectAll(anchor)
{
  let doc = anchor.ownerDocument;
  let dummy = doc.getElementById("dummy");
  let selection = doc.defaultView.getSelection();

  // Copy command will copy invisible elements, make sure not to select too much
  let range = document.createRange();
  range.selectNodeContents(dummy.parentNode);
  if (dummy.offsetHeight)
    range.setStartBefore(dummy);
  else
    range.setStartAfter(dummy);
  selection.removeAllRanges();
  selection.addRange(range);
}

function handleBrowserClick(event)
{
  if (event.button != 0)
    return;

  event.preventDefault();

  let linkNode = event.target;
  while (linkNode && !(linkNode instanceof HTMLAnchorElement))
    linkNode = linkNode.parentNode;
  if (!linkNode)
    return;

  // viewSourceUtils.js would help but it isn't unusable enough in Firefox 3.0
  window.openDialog("chrome://global/content/viewSource.xul", "_blank", "all,dialog=no", linkNode.href, null, null, linkNode.lineNum, false);
}

function editFilters()
{
  let result = {};
  window.openDialog("editfilters.xul", "_blank", "modal,centerscreen,resizable", filters, result);
  if ("include" in result)
  {
    // Save preferences
    try
    {
      let json = JSONServ.encode(result);
      prefService.setCharPref("extensions.jsdeobfuscator.filters", json);
      prefService.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
      updateFiltersUI();
    }
    catch(e)
    {
      Components.utils.reportError(e);
    }
  }
}

function resetFilters()
{
  try
  {
    prefService.clearUserPref("extensions.jsdeobfuscator.filters");
    prefService.QueryInterface(Ci.nsIPrefService).savePrefFile(null);
    updateFiltersUI();
  }
  catch(e)
  {
    Components.utils.reportError(e);
  }
}

var scriptHook =
{
  onScriptCreated: function(script)
  {
    processAction("compiled", script);
  },
  onScriptDestroyed: function(script)
  {
  },
  onCall: function(frame, type)
  {
    if (type == Ci.jsdICallHook.TYPE_TOPLEVEL_START || type == Ci.jsdICallHook.TYPE_FUNCTION_CALL)
      processAction("executed", frame.script);
    else if (type == Ci.jsdICallHook.TYPE_TOPLEVEL_END || type == Ci.jsdICallHook.TYPE_FUNCTION_RETURN)
      processAction("returned", frame.script);
  },
  prevScript: null,
  QueryInterface: XPCOMUtils.generateQI([Ci.jsdIScriptHook, Ci.jsdICallHook])
}
<|endoftext|>


<commit_before>var plugin = document.getElementById("gnome-online-accounts-plugin");
console.log("goa: GNOME Online Accounts background script loading");

var accountData = {};

function generateAccountId(requestData)
{
    if (!requestData || !requestData.provider || !requestData.identity)
        return;
    return "goa|"+requestData.provider+"|"+requestData.identity;
}

function accountDataStore(accountId, data) {
    accountData[accountId] = data;
}

function accountDataContains(accountId) {
    return (accountId in accountData);
}

// Grab the collected data and get rid of it
function accountDataTake(accountId) {
    if (!accountDataContains(accountId))
        return;
    data = accountData[accountId];
    accountDataSterilize(accountId);
    return data;
}

// Get rid of collected data without removing the account id,
// so we can keep track of the accounts already handled
function accountDataSterilize(accountId) {
    accountData[accountId] = false;
}

function accountIsPermanentlyIgnored(accountId)
{
    return localStorage.getItem("ignore-"+accountId);
}

function accountSetPermanentlyIgnored(accountId)
{
    localStorage.setItem("ignore-"+accountId, new Date());
}

function loginDetected(request, sender) {
    var accountId = generateAccountId(request.data);
    if (!accountId)
        return;
    // Do nothing if already dismissed or configured
    if (accountIsPermanentlyIgnored(accountId) || accountDataContains(accountId))
        return;
    var data = {
        collected: request.data,
        tabId: sender.tab.id
    };
    accountDataStore(accountId, data);

    // Show the infobar only if experimental APIs are enabled
    if (chrome.experimental && chrome.experimental.infobars) {
        chrome.experimental.infobars.show({
            tabId: sender.tab.id,
            path: "infobar.html#"+accountId
        });
    }
    chrome.pageAction.setPopup({
        tabId: sender.tab.id,
        popup: "popup.html#"+accountId
    });
    chrome.pageAction.show(sender.tab.id);
}

function accountCreate(request, sender) {
    var accountId = request.accountId;
    console.log("goa: create account", accountId);
    if (!accountId)
        return;
    var data = accountDataTake(accountId);
    console.log("goa: collected data", data);
    // Do nothing if non-existent or already created
    if (!data)
        return;
    chrome.pageAction.hide(data.tabId);
    var collected = data.collected;
    chrome.cookies.getAll({domain:collected.authenticationDomain}, function(cookies) {
        collected.cookies = cookies.map(function(cookie) {
            var c = cookie;
            delete c.storeId;
            console.log("goa: cookie", c);
            return c;
        });
        plugin.loginDetected(JSON.stringify(collected));
    });
};

function accountIgnore(request, sender) {
    var accountId = request.accountId;
    console.log("goa: ignore account '"+accountId+"'");
    if (!accountId)
        return;
    var data = accountDataTake(accountId);
    // Do nothing if non-existent or already created
    if (!data)
        return;
    chrome.pageAction.hide(data.tabId);
    if (accountIsPermanentlyIgnored(accountId))
      return;
    accountSetPermanentlyIgnored(accountId);
};

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
    console.log("goa: Message received", request, "from", sender);
    var ret = {};
    if (typeof(request) == 'object') {
      if (request['type'] == 'login-detected')
        ret = loginDetected(request, sender);
      else if (request['type'] == 'account-create')
        ret = accountCreate(request, sender);
      else if (request['type'] == 'account-ignore')
        ret = accountIgnore(request, sender);
    }
    sendResponse(ret);
});
<commit_msg>chromium: Show infobar once and hide page action icon on old tabs<commit_after>var plugin = document.getElementById("gnome-online-accounts-plugin");
console.log("goa: GNOME Online Accounts background script loading");

var accountData = {};

function generateAccountId(requestData)
{
    if (!requestData || !requestData.provider || !requestData.identity)
        return;
    return "goa|"+requestData.provider+"|"+requestData.identity;
}

function accountDataStore(accountId, data) {
    accountData[accountId] = data;
}

function accountDataContains(accountId) {
    return (accountId in accountData);
}

// Grab the collected data and get rid of it
function accountDataTake(accountId) {
    if (!accountDataContains(accountId))
        return;
    data = accountData[accountId];
    accountDataSterilize(accountId);
    return data;
}

function accountDataPeek(accountId) {
    if (!accountDataContains(accountId))
        return;
    return accountData[accountId];
}

// Get rid of collected data without removing the account id,
// so we can keep track of the accounts already handled
function accountDataSterilize(accountId) {
    accountData[accountId] = false;
}

function accountDataIsSterilized(accountId) {
    return accountData[accountId] === false;
}

function accountIsPermanentlyIgnored(accountId)
{
    return localStorage.getItem("ignore-"+accountId);
}

function accountSetPermanentlyIgnored(accountId)
{
    localStorage.setItem("ignore-"+accountId, new Date());
}

function loginDetected(request, sender) {
    var accountId = generateAccountId(request.data);
    if (!accountId)
        return;
    // Do nothing if already dismissed or configured
    if (accountIsPermanentlyIgnored(accountId) || accountDataIsSterilized(accountId))
        return;
    // Cleanup the page action icon on the old tab, if any
    var oldData = accountDataPeek(accountId);
    if (oldData && oldData.tabId != sender.tab.id)
        chrome.pageAction.hide(oldData.tabId);
    // Store/Refresh the collected data
    var data = {
        collected: request.data,
        tabId: sender.tab.id
    };
    accountDataStore(accountId, data);

    // Show the infobar only if experimental APIs are enabled
    if (chrome.experimental && chrome.experimental.infobars) {
        // Show the infobar the first time only
        if (!oldData) {
            chrome.experimental.infobars.show({
                tabId: sender.tab.id,
                path: "infobar.html#"+accountId
            });
        }
    }
    chrome.pageAction.setPopup({
        tabId: sender.tab.id,
        popup: "popup.html#"+accountId
    });
    chrome.pageAction.show(sender.tab.id);
}

function accountCreate(request, sender) {
    var accountId = request.accountId;
    console.log("goa: create account", accountId);
    if (!accountId)
        return;
    var data = accountDataTake(accountId);
    console.log("goa: collected data", data);
    // Do nothing if non-existent or already created
    if (!data)
        return;
    chrome.pageAction.hide(data.tabId);
    var collected = data.collected;
    chrome.cookies.getAll({domain:collected.authenticationDomain}, function(cookies) {
        collected.cookies = cookies.map(function(cookie) {
            var c = cookie;
            delete c.storeId;
            console.log("goa: cookie", c);
            return c;
        });
        plugin.loginDetected(JSON.stringify(collected));
    });
};

function accountIgnore(request, sender) {
    var accountId = request.accountId;
    console.log("goa: ignore account '"+accountId+"'");
    if (!accountId)
        return;
    var data = accountDataTake(accountId);
    // Do nothing if non-existent or already created
    if (!data)
        return;
    chrome.pageAction.hide(data.tabId);
    if (accountIsPermanentlyIgnored(accountId))
      return;
    accountSetPermanentlyIgnored(accountId);
};

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
    console.log("goa: Message received", request, "from", sender);
    var ret = {};
    if (typeof(request) == 'object') {
      if (request['type'] == 'login-detected')
        ret = loginDetected(request, sender);
      else if (request['type'] == 'account-create')
        ret = accountCreate(request, sender);
      else if (request['type'] == 'account-ignore')
        ret = accountIgnore(request, sender);
    }
    sendResponse(ret);
});
<|endoftext|>