<commit_before>"use strict";

/**
 * Copyright 2017 XcooBee LLC

 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const chalk = require("chalk");

const runTest = (argv, callback) => {
    const path = require("path");
    const fs = require("fs-extra");
    const util = require("./util");

    // The default path to the parameters.json file, not necessary it exists
    let parametersFilePath = path.resolve("./parameters.json");

    // The default path for the workFiles and output directories
    let outputPath = path.resolve(".");

    // The full path to workFiles directory
    let workFilesPath = null;

    // The full path to output directory
    let outputFilesPath = null;

    // The default ttl, changes with size
    let ttl = 30000;
    // How long have we been running?
    let ellapsed = 0;

    // The amount of time reserved for clean up tasks
    const timeToCleanUp = 5000;

    // Track the number of open write streams
    const streamArray = [];

    // Flag to determine if the bee timed-out
    let callbackCalled = false;

    // mail object to be written
    const mailObject = [];

    // log object to be written
    const logObject = [];

    // processing object to be written
    const processingObject = [];

    // contains information about input files
    let filesInfo = {};

    // path to info file
    let infoFilePath = null;

    // bee system params
    let beeSystemParams = {};

    const closeStreams = () => {
        streamArray.forEach((value) => {
            value.close();
        });
    };

    let globalSequence = 1;
    const getNextId = () => {
        const current = globalSequence;
        globalSequence += 1;
        return current;
    };

    // The number of requested streams in the output folder
    let requestedStreamsInOutput = 0;

    const createServices = (inputFilePath) => {
        // TODO: Validation for fileName, what should happen if the user requests a writeStream for an
        // already created fileName
        // Create the services object
        const readStream = fs.createReadStream(inputFilePath);
        const services = {
            // Just log a message to the system console
            log: (message, type, replacement = {}) => {
                logObject.push({ date: Date.now(), type, message, replacement });
            },
            // email service to mock the sending of an email
            mail: (recipient, template, replacement) => {
                mailObject.push({ recipient, template, replacement });
            },
            getNextId,
            addParam: (key, value) => {
                processingObject.push({ key, value });
            },
            timeToRun: () => ttl - ellapsed,
            // The default streams for reading and writing
            readStream: () => readStream,
            // TODO: Should overwrite the files
            writeStreamManager: {
                getWriteStream: (fileName, type) => {
                    const filesBlackList = [
                        "xcoobeemail.json",
                        "xcoobeelog.json",
                        "xcoobeeparam.json",
                    ];

                    if (filesBlackList.indexOf(fileName.toLowerCase()) !== -1) {
                        return callback(Error(`Attempted to use reserved file name '${fileName}'`));
                    }

                    if (type === "output") {
                        requestedStreamsInOutput += 1;
                    }

                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createWriteStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    if (stream) streamArray.push(stream);
                    return stream;
                },
                getReadStream: (fileName, type) => {
                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createReadStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    return stream;
                },
            },
            getFileType: filename => (filesInfo[filename] && filesInfo[filename].file_type) || 999,
            getFileTags: filename => (filesInfo[filename] && filesInfo[filename].file_tags) || ["one", "two", "three"],
            validationError: field => services.log(`Input value for '${field}' is not correct`, "error"),
            setBalanceLock: () => Promise.resolve(true),
            getBeeParam: param => beeSystemParams[param],
        };

        return services;
    };

    const showHelp = argv.indexOf("--help") !== -1;
    if (showHelp) {
        const marked = require("marked");
        const TerminalRenderer = require("marked-terminal");
        marked.setOptions({
            renderer: new TerminalRenderer(),
            gfm: true,
            tables: true,
            breaks: false,
            pedantic: false,
            sanitize: false,
            smartLists: true,
            smartypants: false,
        });
        let helpText = fs.readFileSync("./src/assets/help.md");
        if (helpText) helpText = helpText.toString("utf-8");
        console.log(marked(`${helpText}`));
        return callback(null, "Success");
    }

    const overWriteFiles = argv.indexOf("-o") !== -1;

    // Assume we are on the node project directory
    // unless otherwise specified by the --bee switch
    let beeModule = null;
    let pathToBee;
    try {
        const beeIndex = argv.indexOf("--bee");
        if (beeIndex !== -1) {
            pathToBee = path.resolve(argv[beeIndex + 1]);
            beeModule = require(pathToBee); // eslint-disable-line import/no-dynamic-require
        } else {
            // TODO: Don't rely on cwd
            beeModule = require(process.cwd()); // eslint-disable-line import/no-dynamic-require
        }
    } catch (err) {
        callback(new Error("It was not possible to load the bee, make sure you are inside a valid node project or use the '--bee' switch"));
    }

    // Set the size instance in which this bee will be run
    // We use the size to, among other things, choose the proper ttl
    const sizeIndex = argv.indexOf("--size");
    let size = "s";
    if (sizeIndex !== -1) {
        const validSizes = ["s", "m", "l"];
        size = argv[sizeIndex + 1].toLowerCase();
        if (validSizes.indexOf(size) === -1) {
            callback(new Error(`'${size}' is not a valid size, must be one of [s, m, l]`));
        }

        if (size === "s") {
            ttl = 30000;
        } else if (size === "m") {
            ttl = 150000;
        } else {
            ttl = 300000;
        }
    }

    // Substract the timeToCleanUp from ttl to get the net time the bee got available
    ttl -= timeToCleanUp;

    // If no params file are provided we assume the bee won't require integrations
    // nor parameters, unless the '--params' flag is used in which case it is, probably,
    // an user error pointing to an unexistent file
    const paramsIndex = argv.indexOf("--params");
    if (paramsIndex !== -1) {
        parametersFilePath = path.resolve(argv[paramsIndex + 1]);

        if (!fs.existsSync(parametersFilePath)) {
            callback(Error(`${parametersFilePath} doesn't exist`));
        }
    }

    // receive additional information about files
    const infoIndex = argv.indexOf("--info");
    if (infoIndex !== -1) {
        infoFilePath = path.resolve(argv[infoIndex + 1]);

        if (!fs.existsSync(infoFilePath)) {
            callback(Error(`${infoFilePath} doesn't exist`));
        }
    }

    // If the user specifies the output as a directory, use a default file name 'output' with no extension
    // The output directory must exists, the utility WON'T create it
    const outputIndex = argv.indexOf("--out");
    if (outputIndex !== -1) {
        outputPath = path.resolve(argv[outputIndex + 1]);

        try {
            const stats = fs.lstatSync(outputPath);

            if (!stats.isDirectory()) {
                callback(new Error(`${outputPath} is not a valid directory`));
            }
        } catch (err) {
            callback(new Error(`${outputPath} is unknown`));
        }
    }

    // Be extremely careful to not delete a sensitive folder
    outputFilesPath = `${outputPath}${path.sep}output`;
    workFilesPath = `${outputPath}${path.sep}workFiles`;

    if (!fs.existsSync(outputFilesPath)) {
        fs.mkdirSync(outputFilesPath);
    } else if (overWriteFiles) {
        fs.emptyDirSync(outputFilesPath);
    }

    if (!fs.existsSync(workFilesPath)) {
        fs.mkdirSync(workFilesPath);
    } else if (overWriteFiles) {
        fs.emptyDirSync(workFilesPath);
    }

    // The input file must be the first argument
    const inputFilePath = path.resolve(argv[2]);

    if (!fs.existsSync(inputFilePath)) {
        callback(new Error(`Input file '${inputFilePath}' doesn't exist`));
    }

    const services = createServices(inputFilePath);

    const data = {};

    const defaultUserData = {
        first_name: "John",
        last_name: "Testerson",
        xcoobee_id: "~johnt",
        locale: "en-us",
    };

    let parametersContent = null;

    if (fs.existsSync(parametersFilePath)) {
        try {
            parametersContent = JSON.parse(fs.readFileSync(parametersFilePath, "utf8"));
            data.integrations = parametersContent.integrations;
            data.parameters = parametersContent.parameters;
            data.flightprocessing = parametersContent.flightprocessing;
            data.user_data = parametersContent.user_data || defaultUserData;
            data.transaction_key = parametersContent.transaction_key;
            beeSystemParams = parametersContent.bee_system_params || {};
        } catch (err) {
            callback(new Error(`${parametersFilePath} is not a valid JSON file`));
        }
    }

    if (infoFilePath && fs.existsSync(infoFilePath)) {
        try {
            filesInfo = JSON.parse(fs.readFileSync(infoFilePath, "utf8"));
        } catch (err) {
            callback(new Error(`${infoFilePath} is not a valid JSON file`));
        }
    }

    const outputXcoobeeObjects = () => {
        if (logObject.length > 0) {
            fs.writeFileSync(path.join(outputFilesPath, "xcoobeelog.json"), JSON.stringify(logObject, null, 2));
        }

        if (mailObject.length > 0) {
            fs.writeFileSync(path.join(outputFilesPath, "xcoobeemail.json"), JSON.stringify(mailObject, null, 2));
        }

        if (processingObject.length > 0) {
            fs.writeFileSync(path.join(outputFilesPath, "xcoobeeparam.json"), JSON.stringify(processingObject, null, 2));
        }
    };

    setInterval(() => {
        ellapsed += 2;
    }, 2);

    setTimeout(() => {
        if (!callbackCalled) {
            clearInterval();
            closeStreams();
            outputXcoobeeObjects();
            util.prune(outputFilesPath);
            util.prune(workFilesPath);
            callback(new Error("Timed-out"));
        }
    }, ttl);

    const beeCallback = (err, result) => {
        callbackCalled = true;
        clearInterval();
        closeStreams();

        util.prune(outputFilesPath);
        util.prune(workFilesPath);

        outputXcoobeeObjects();

        const outputFolderSize = util.sizeOfFolder(outputFilesPath);
        const workFolderSize = util.sizeOfFolder(workFilesPath);

        const totalSize = outputFolderSize + workFolderSize;
        const issueSizeWarning = totalSize >= 536870912;
        console.log(`
==========================================
Bee test result completed
==========================================
status: Success
instance: ${size}
time: ${chalk.green(ellapsed)}ms
space: ${issueSizeWarning ? chalk.red(totalSize) : chalk.green(totalSize)} bytes ${issueSizeWarning ? "--->WARNING" : ""}
        `);

        if (requestedStreamsInOutput > 1) {
            console.log(chalk.yellow(`*More than one write stream requested in module ${pathToBee}, make sure to mark it as splitter.`));
        }

        if (err) {
            return callback(err);
        }

        return callback(null, result);
    };
    beeModule.flight(services, data, beeCallback);
};

if (require.main === module) {
    const callback = (err) => {
        if (err) {
            console.log(`
==========================================
Bee test result completed
==========================================
status: ${chalk.red("Failure")}
reason: ${err.message}
        `);
            return process.exit(1);
        }
        return process.exit(0);
    };
    runTest(process.argv, callback);
}

module.exports.runTest = (argv, callback) => {
    runTest(argv, callback);
};
<commit_msg>pass `metadata` from parameters file to bee<commit_after>"use strict";

/**
 * Copyright 2017 XcooBee LLC

 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const chalk = require("chalk");

const runTest = (argv, callback) => {
    const path = require("path");
    const fs = require("fs-extra");
    const util = require("./util");

    // The default path to the parameters.json file, not necessary it exists
    let parametersFilePath = path.resolve("./parameters.json");

    // The default path for the workFiles and output directories
    let outputPath = path.resolve(".");

    // The full path to workFiles directory
    let workFilesPath = null;

    // The full path to output directory
    let outputFilesPath = null;

    // The default ttl, changes with size
    let ttl = 30000;
    // How long have we been running?
    let ellapsed = 0;

    // The amount of time reserved for clean up tasks
    const timeToCleanUp = 5000;

    // Track the number of open write streams
    const streamArray = [];

    // Flag to determine if the bee timed-out
    let callbackCalled = false;

    // mail object to be written
    const mailObject = [];

    // log object to be written
    const logObject = [];

    // processing object to be written
    const processingObject = [];

    // contains information about input files
    let filesInfo = {};

    // path to info file
    let infoFilePath = null;

    // bee system params
    let beeSystemParams = {};

    const closeStreams = () => {
        streamArray.forEach((value) => {
            value.close();
        });
    };

    let globalSequence = 1;
    const getNextId = () => {
        const current = globalSequence;
        globalSequence += 1;
        return current;
    };

    // The number of requested streams in the output folder
    let requestedStreamsInOutput = 0;

    const createServices = (inputFilePath) => {
        // TODO: Validation for fileName, what should happen if the user requests a writeStream for an
        // already created fileName
        // Create the services object
        const readStream = fs.createReadStream(inputFilePath);
        const services = {
            // Just log a message to the system console
            log: (message, type, replacement = {}) => {
                logObject.push({ date: Date.now(), type, message, replacement });
            },
            // email service to mock the sending of an email
            mail: (recipient, template, replacement) => {
                mailObject.push({ recipient, template, replacement });
            },
            getNextId,
            addParam: (key, value) => {
                processingObject.push({ key, value });
            },
            timeToRun: () => ttl - ellapsed,
            // The default streams for reading and writing
            readStream: () => readStream,
            // TODO: Should overwrite the files
            writeStreamManager: {
                getWriteStream: (fileName, type) => {
                    const filesBlackList = [
                        "xcoobeemail.json",
                        "xcoobeelog.json",
                        "xcoobeeparam.json",
                    ];

                    if (filesBlackList.indexOf(fileName.toLowerCase()) !== -1) {
                        return callback(Error(`Attempted to use reserved file name '${fileName}'`));
                    }

                    if (type === "output") {
                        requestedStreamsInOutput += 1;
                    }

                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createWriteStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    if (stream) streamArray.push(stream);
                    return stream;
                },
                getReadStream: (fileName, type) => {
                    const typePath = type === "wip" ? "workFiles" : "output";
                    const stream = fs.createReadStream(`${outputPath}${path.sep}${typePath}${path.sep}${fileName}`);
                    return stream;
                },
            },
            getFileType: filename => (filesInfo[filename] && filesInfo[filename].file_type) || 999,
            getFileTags: filename => (filesInfo[filename] && filesInfo[filename].file_tags) || ["one", "two", "three"],
            validationError: field => services.log(`Input value for '${field}' is not correct`, "error"),
            setBalanceLock: () => Promise.resolve(true),
            getBeeParam: param => beeSystemParams[param],
        };

        return services;
    };

    const showHelp = argv.indexOf("--help") !== -1;
    if (showHelp) {
        const marked = require("marked");
        const TerminalRenderer = require("marked-terminal");
        marked.setOptions({
            renderer: new TerminalRenderer(),
            gfm: true,
            tables: true,
            breaks: false,
            pedantic: false,
            sanitize: false,
            smartLists: true,
            smartypants: false,
        });
        let helpText = fs.readFileSync("./src/assets/help.md");
        if (helpText) helpText = helpText.toString("utf-8");
        console.log(marked(`${helpText}`));
        return callback(null, "Success");
    }

    const overWriteFiles = argv.indexOf("-o") !== -1;

    // Assume we are on the node project directory
    // unless otherwise specified by the --bee switch
    let beeModule = null;
    let pathToBee;
    try {
        const beeIndex = argv.indexOf("--bee");
        if (beeIndex !== -1) {
            pathToBee = path.resolve(argv[beeIndex + 1]);
            beeModule = require(pathToBee); // eslint-disable-line import/no-dynamic-require
        } else {
            // TODO: Don't rely on cwd
            beeModule = require(process.cwd()); // eslint-disable-line import/no-dynamic-require
        }
    } catch (err) {
        callback(new Error("It was not possible to load the bee, make sure you are inside a valid node project or use the '--bee' switch"));
    }

    // Set the size instance in which this bee will be run
    // We use the size to, among other things, choose the proper ttl
    const sizeIndex = argv.indexOf("--size");
    let size = "s";
    if (sizeIndex !== -1) {
        const validSizes = ["s", "m", "l"];
        size = argv[sizeIndex + 1].toLowerCase();
        if (validSizes.indexOf(size) === -1) {
            callback(new Error(`'${size}' is not a valid size, must be one of [s, m, l]`));
        }

        if (size === "s") {
            ttl = 30000;
        } else if (size === "m") {
            ttl = 150000;
        } else {
            ttl = 300000;
        }
    }

    // Substract the timeToCleanUp from ttl to get the net time the bee got available
    ttl -= timeToCleanUp;

    // If no params file are provided we assume the bee won't require integrations
    // nor parameters, unless the '--params' flag is used in which case it is, probably,
    // an user error pointing to an unexistent file
    const paramsIndex = argv.indexOf("--params");
    if (paramsIndex !== -1) {
        parametersFilePath = path.resolve(argv[paramsIndex + 1]);

        if (!fs.existsSync(parametersFilePath)) {
            callback(Error(`${parametersFilePath} doesn't exist`));
        }
    }

    // receive additional information about files
    const infoIndex = argv.indexOf("--info");
    if (infoIndex !== -1) {
        infoFilePath = path.resolve(argv[infoIndex + 1]);

        if (!fs.existsSync(infoFilePath)) {
            callback(Error(`${infoFilePath} doesn't exist`));
        }
    }

    // If the user specifies the output as a directory, use a default file name 'output' with no extension
    // The output directory must exists, the utility WON'T create it
    const outputIndex = argv.indexOf("--out");
    if (outputIndex !== -1) {
        outputPath = path.resolve(argv[outputIndex + 1]);

        try {
            const stats = fs.lstatSync(outputPath);

            if (!stats.isDirectory()) {
                callback(new Error(`${outputPath} is not a valid directory`));
            }
        } catch (err) {
            callback(new Error(`${outputPath} is unknown`));
        }
    }

    // Be extremely careful to not delete a sensitive folder
    outputFilesPath = `${outputPath}${path.sep}output`;
    workFilesPath = `${outputPath}${path.sep}workFiles`;

    if (!fs.existsSync(outputFilesPath)) {
        fs.mkdirSync(outputFilesPath);
    } else if (overWriteFiles) {
        fs.emptyDirSync(outputFilesPath);
    }

    if (!fs.existsSync(workFilesPath)) {
        fs.mkdirSync(workFilesPath);
    } else if (overWriteFiles) {
        fs.emptyDirSync(workFilesPath);
    }

    // The input file must be the first argument
    const inputFilePath = path.resolve(argv[2]);

    if (!fs.existsSync(inputFilePath)) {
        callback(new Error(`Input file '${inputFilePath}' doesn't exist`));
    }

    const services = createServices(inputFilePath);

    const data = {};

    const defaultUserData = {
        first_name: "John",
        last_name: "Testerson",
        xcoobee_id: "~johnt",
        locale: "en-us",
    };

    let parametersContent = null;

    if (fs.existsSync(parametersFilePath)) {
        try {
            parametersContent = JSON.parse(fs.readFileSync(parametersFilePath, "utf8"));
            data.integrations = parametersContent.integrations;
            data.parameters = parametersContent.parameters;
            data.metadata = parametersContent.metadata;
            data.flightprocessing = parametersContent.flightprocessing;
            data.user_data = parametersContent.user_data || defaultUserData;
            data.transaction_key = parametersContent.transaction_key;
            beeSystemParams = parametersContent.bee_system_params || {};
        } catch (err) {
            callback(new Error(`${parametersFilePath} is not a valid JSON file`));
        }
    }

    if (infoFilePath && fs.existsSync(infoFilePath)) {
        try {
            filesInfo = JSON.parse(fs.readFileSync(infoFilePath, "utf8"));
        } catch (err) {
            callback(new Error(`${infoFilePath} is not a valid JSON file`));
        }
    }

    const outputXcoobeeObjects = () => {
        if (logObject.length > 0) {
            fs.writeFileSync(path.join(outputFilesPath, "xcoobeelog.json"), JSON.stringify(logObject, null, 2));
        }

        if (mailObject.length > 0) {
            fs.writeFileSync(path.join(outputFilesPath, "xcoobeemail.json"), JSON.stringify(mailObject, null, 2));
        }

        if (processingObject.length > 0) {
            fs.writeFileSync(path.join(outputFilesPath, "xcoobeeparam.json"), JSON.stringify(processingObject, null, 2));
        }
    };

    setInterval(() => {
        ellapsed += 2;
    }, 2);

    setTimeout(() => {
        if (!callbackCalled) {
            clearInterval();
            closeStreams();
            outputXcoobeeObjects();
            util.prune(outputFilesPath);
            util.prune(workFilesPath);
            callback(new Error("Timed-out"));
        }
    }, ttl);

    const beeCallback = (err, result) => {
        callbackCalled = true;
        clearInterval();
        closeStreams();

        util.prune(outputFilesPath);
        util.prune(workFilesPath);

        outputXcoobeeObjects();

        const outputFolderSize = util.sizeOfFolder(outputFilesPath);
        const workFolderSize = util.sizeOfFolder(workFilesPath);

        const totalSize = outputFolderSize + workFolderSize;
        const issueSizeWarning = totalSize >= 536870912;
        console.log(`
==========================================
Bee test result completed
==========================================
status: Success
instance: ${size}
time: ${chalk.green(ellapsed)}ms
space: ${issueSizeWarning ? chalk.red(totalSize) : chalk.green(totalSize)} bytes ${issueSizeWarning ? "--->WARNING" : ""}
        `);

        if (requestedStreamsInOutput > 1) {
            console.log(chalk.yellow(`*More than one write stream requested in module ${pathToBee}, make sure to mark it as splitter.`));
        }

        if (err) {
            return callback(err);
        }

        return callback(null, result);
    };
    beeModule.flight(services, data, beeCallback);
};

if (require.main === module) {
    const callback = (err) => {
        if (err) {
            console.log(`
==========================================
Bee test result completed
==========================================
status: ${chalk.red("Failure")}
reason: ${err.message}
        `);
            return process.exit(1);
        }
        return process.exit(0);
    };
    runTest(process.argv, callback);
}

module.exports.runTest = (argv, callback) => {
    runTest(argv, callback);
};
<|endoftext|>


<commit_before>var SuperPixelGrid = function (w, h , initArray) {
    if (!(this instanceof SuperPixelGrid)) {
        return new SuperPixelGrid(w, h, initArray);
    }
    Array2d.call(this, w, h, initArray);
};
SuperPixelGrid.prototype = new Array2d();
SuperPixelGrid.prototype.constructor = SuperPixelGrid;

SuperPixelGrid.prototype.togglePixel = function(x, y) {
      this.set(x, y, !this.get(x, y));
};

SuperPixelGrid.prototype.drawLine = function(x0, y0, x1, y1, color) {
    var self = this;
    self.forLine(x0, y0, x1, y1, function(val, x, y) {self.set(x, y, color);});
    return this;
};

SuperPixelGrid.prototype.drawRectangle = function(x0, y0, x1, y1, color) {
    this.drawLine(x0, y0, x1, y0, color);
    this.drawLine(x1, y0, x1, y1, color);
    this.drawLine(x1, y1, x0, y1, color);
    this.drawLine(x0, y1, x0, y0, color);
    return this;
};

SuperPixelGrid.prototype.drawEllipse = function(x0, y0, x1, y1, color) {
    var self = this;
    var plot4EllipsePoints = function(x, y, color) {
        self.set(x0 + x, y0 + y, color);
        self.set(x0 - x, y0 + y, color);
        self.set(x0 - x, y0 - y, color);
        self.set(x0 + x, y0 - y, color);
    };
    var a = Math.abs(x1 - x0);
    var b = Math.abs(y1 - y0);
    var b1 = b % 2;
    var dx = 4 * (1 - a) * b * b;
    var dy = 4 * (b1 + 1) * a * a;
    var err = dx + dy + b1 * a * a;
    var e2;

    if (x0 > x1) {
        x0 = x1;
        x1 += a;
    }
    if (y0 > y1) {
        y0 = y1;
    }
    y0 += Math.round((b + 1) / 2);
    y1 = y0 - b1;
    a = a * 8 * a;
    b1 = 8 * b * b;

    do {
        self.set(x1, y0, color);
        self.set(x0, y0, color);
        self.set(x0, y1, color);
        self.set(x1, y1, color);
        e2 = 2 * err;
        if (e2 <= dy) {
            y0++;
            y1--;
            err += dy += a;
        }
        if (e2 >= dx || 2 * err > dy) {
            x0++;
            x1--;
            err += dx += b1;
        }
    } while (x0 <= x1);

    while (y0-y1 < b) {
       self.set(x0 - 1, y0, color);
       self.set(x1 + 1, y0++, color);
       self.set(x0 - 1, y1, color);
       self.set(x1 + 1, y1--, color);
    }
};

SuperPixelGrid.prototype.floodFill = function(x, y, color) {
  // if pixel is already toggled, stop
  if (this.get(x, y) != color) {
    this.set(x, y, color);
    // fill up
    if (y > 0) {
      this.floodFill(x, y - 1, color);
    }
    // fill down
    if (y < this.height - 1) {
      this.floodFill(x, y + 1, color);
    }
    // fill left
    if (x > 0) {
      this.floodFill(x - 1, y, color);
    }
    // fill right
    if (x < this.width - 1) {
      this.floodFill(x + 1, y, color);
    }
  }
  return this;
};

SuperPixelGrid.prototype.lifeStep = function() {
    var self = this;
    var newFrame = self.map( function(value, x, y, w, h) {
      var neighbors = [];
      if (x > 0) {
        if (y > 0) { neighbors.push(self.get(x - 1, y - 1)); }
        neighbors.push(self.get(x - 1, y));
        if (y < self.height - 1) { neighbors.push(self.get(x - 1, y + 1)); }
      }
      if (y > 0) { neighbors.push(self.get(x, y - 1)); }
      if (y < self.height - 1) { neighbors.push(self.get(x, y + 1)); }
      if (x < self.width - 1) {
        if (y > 0) { neighbors.push(self.get(x + 1, y - 1)); }
        neighbors.push(self.get(x + 1, y));
        if (y < self.height + 1) { neighbors.push(self.get(x + 1, y + 1)); }
      }
      var liveNeighbors = neighbors
        .map( function(isTrue) {return isTrue ? 1 : 0;} ) //map bool to int
        .reduce( function(a,b) {return a + b;} ); //sum
      if (value === true) { // this cell is 'alive'
        if (liveNeighbors < 2 || liveNeighbors > 3) {
          return false;
        }
        else {
          return true;
        }
      } else { //this cell is 'dead'
        if (liveNeighbors === 3) {
          return true;
        } else {
          return false;
        }
      }
    });
    this.rawArray = newFrame.rawArray.slice();
    return this;
};

SuperPixelGrid.prototype.toString = function() {
    return this.rawArray.map( function(n){return n ? 1 : 0;} ).join('');
};

SuperPixelGrid.prototype.fromString = function(s) {
    var rawArray = s.split("").map( function(n) {return n == 1;} );
    this.rawArray = rawArray.slice();
    return this;
};

<commit_msg>Change circle algorithm to draw from midpoint<commit_after>var SuperPixelGrid = function (w, h , initArray) {
    if (!(this instanceof SuperPixelGrid)) {
        return new SuperPixelGrid(w, h, initArray);
    }
    Array2d.call(this, w, h, initArray);
};
SuperPixelGrid.prototype = new Array2d();
SuperPixelGrid.prototype.constructor = SuperPixelGrid;

SuperPixelGrid.prototype.togglePixel = function(x, y) {
      this.set(x, y, !this.get(x, y));
};

SuperPixelGrid.prototype.drawLine = function(x0, y0, x1, y1, color) {
    var self = this;
    self.forLine(x0, y0, x1, y1, function(val, x, y) {self.set(x, y, color);});
    return this;
};

SuperPixelGrid.prototype.drawRectangle = function(x0, y0, x1, y1, color) {
    this.drawLine(x0, y0, x1, y0, color);
    this.drawLine(x1, y0, x1, y1, color);
    this.drawLine(x1, y1, x0, y1, color);
    this.drawLine(x0, y1, x0, y0, color);
    return this;
};

SuperPixelGrid.prototype.drawEllipse = function(x0, y0, x1, y1, color) {
    var self = this;
    x0 = 2 * x0 - x1;
    y0 = 2 * y0 - y1;
    var plot4EllipsePoints = function(x, y, color) {
        self.set(x0 + x, y0 + y, color);
        self.set(x0 - x, y0 + y, color);
        self.set(x0 - x, y0 - y, color);
        self.set(x0 + x, y0 - y, color);
    };
    var a = Math.abs(x1 - x0);
    var b = Math.abs(y1 - y0);
    var b1 = b % 2;
    var dx = 4 * (1 - a) * b * b;
    var dy = 4 * (b1 + 1) * a * a;
    var err = dx + dy + b1 * a * a;
    var e2;

    if (x0 > x1) {
        x0 = x1;
        x1 += a;
    }
    if (y0 > y1) {
        y0 = y1;
    }
    y0 += Math.round((b + 1) / 2);
    y1 = y0 - b1;
    a = a * 8 * a;
    b1 = 8 * b * b;

    do {
        self.set(x1, y0, color);
        self.set(x0, y0, color);
        self.set(x0, y1, color);
        self.set(x1, y1, color);
        e2 = 2 * err;
        if (e2 <= dy) {
            y0++;
            y1--;
            err += dy += a;
        }
        if (e2 >= dx || 2 * err > dy) {
            x0++;
            x1--;
            err += dx += b1;
        }
    } while (x0 <= x1);

    while (y0-y1 < b) {
       self.set(x0 - 1, y0, color);
       self.set(x1 + 1, y0++, color);
       self.set(x0 - 1, y1, color);
       self.set(x1 + 1, y1--, color);
    }
};

SuperPixelGrid.prototype.floodFill = function(x, y, color) {
  // if pixel is already toggled, stop
  if (this.get(x, y) != color) {
    this.set(x, y, color);
    // fill up
    if (y > 0) {
      this.floodFill(x, y - 1, color);
    }
    // fill down
    if (y < this.height - 1) {
      this.floodFill(x, y + 1, color);
    }
    // fill left
    if (x > 0) {
      this.floodFill(x - 1, y, color);
    }
    // fill right
    if (x < this.width - 1) {
      this.floodFill(x + 1, y, color);
    }
  }
  return this;
};

SuperPixelGrid.prototype.lifeStep = function() {
    var self = this;
    var newFrame = self.map( function(value, x, y, w, h) {
      var neighbors = [];
      if (x > 0) {
        if (y > 0) { neighbors.push(self.get(x - 1, y - 1)); }
        neighbors.push(self.get(x - 1, y));
        if (y < self.height - 1) { neighbors.push(self.get(x - 1, y + 1)); }
      }
      if (y > 0) { neighbors.push(self.get(x, y - 1)); }
      if (y < self.height - 1) { neighbors.push(self.get(x, y + 1)); }
      if (x < self.width - 1) {
        if (y > 0) { neighbors.push(self.get(x + 1, y - 1)); }
        neighbors.push(self.get(x + 1, y));
        if (y < self.height + 1) { neighbors.push(self.get(x + 1, y + 1)); }
      }
      var liveNeighbors = neighbors
        .map( function(isTrue) {return isTrue ? 1 : 0;} ) //map bool to int
        .reduce( function(a,b) {return a + b;} ); //sum
      if (value === true) { // this cell is 'alive'
        if (liveNeighbors < 2 || liveNeighbors > 3) {
          return false;
        }
        else {
          return true;
        }
      } else { //this cell is 'dead'
        if (liveNeighbors === 3) {
          return true;
        } else {
          return false;
        }
      }
    });
    this.rawArray = newFrame.rawArray.slice();
    return this;
};

SuperPixelGrid.prototype.toString = function() {
    return this.rawArray.map( function(n){return n ? 1 : 0;} ).join('');
};

SuperPixelGrid.prototype.fromString = function(s) {
    var rawArray = s.split("").map( function(n) {return n == 1;} );
    this.rawArray = rawArray.slice();
    return this;
};

<|endoftext|>


<commit_before>
const COORD_CHILDREN = {}; // only allocate children coords once per coord

export const TileID = {

    coord(c) {
        return {x: c.x, y: c.y, z: c.z, key: this.coordKey(c)};
    },

    coordKey({x, y, z}) {
        return x + '/' + y + '/' + z;
    },

    key (coords, source, style_z) {
        if (coords.y < 0 || coords.y >= (1 << coords.z) || coords.z < 0) {
            return; // cull tiles out of range (x will wrap)
        }
        return [source.name, style_z, coords.x, coords.y, coords.z].join('/');
    },

    normalizedKey (coords, source, style_z) {
        return this.key(this.normalizedCoord(coords, source), source, style_z);
    },

    normalizedCoord (coords, source) {
        if (source.zoom_bias) {
            coords = this.coordAtZoom(coords, coords.z - source.zoom_bias);
        }
        return this.coordWithMaxZoom(coords, source.max_zoom);
    },

    coordAtZoom({x, y, z}, zoom) {
        zoom = Math.max(0, zoom); // zoom can't go below zero
        if (z !== zoom) {
            let zscale = Math.pow(2, z - zoom);
            x = Math.floor(x / zscale);
            y = Math.floor(y / zscale);
            z = zoom;
        }
        return this.coord({x, y, z});
    },

    coordWithMaxZoom({x, y, z}, max_zoom) {
        if (max_zoom != null && z > max_zoom) {
            return this.coordAtZoom({x, y, z}, max_zoom);
        }
        return this.coord({x, y, z});
    },

    childrenForCoord({x, y, z, key}) {
        if (!COORD_CHILDREN[key]) {
            z++;
            x *= 2;
            y *= 2;
            COORD_CHILDREN[key] = [
                this.coord({x, y,      z}), this.coord({x: x+1, y,      z}),
                this.coord({x, y: y+1, z}), this.coord({x: x+1, y: y+1, z})
            ];
        }
        return COORD_CHILDREN[key];
    },

    isDescendant(parent, descendant) {
        if (descendant.z > parent.z) {
            let {x, y} = this.coordAtZoom(descendant, parent.z);
            return (parent.x === x && parent.y === y);
        }
        return false;
    },

    // Return identifying info for tile's parent tile
    parent ({ coords, source, style_z }) {
        if (style_z > source.max_coord_zoom || style_z <= source.min_coord_zoom) {
            if (style_z > 0) { // no more tiles above style zoom 0
                return {
                    key: this.key(coords, source, style_z - 1),
                    coords,
                    style_z: style_z - 1,
                    source
                };
            }
            return;
        }
        else if (style_z > 0) { // no more tiles above style zoom 0
            const c = this.coordAtZoom(coords, coords.z - 1);
            return {
                key: this.key(c, source, style_z - 1),
                coords: c,
                style_z: style_z - 1,
                source
            };
        }
    },

    // Return identifying info for tile's child tiles
    children ({ coords, source, style_z }) {
        if (style_z >= source.max_coord_zoom || style_z < source.min_coord_zoom) {
            return [{
                key: this.key(coords, source, style_z + 1),
                coords,
                style_z: style_z + 1,
                source
            }];
        }

        const children = this.childrenForCoord(coords);
        return children.map(c => {
            return {
                key: this.key(c, source, style_z + 1),
                coords: c,
                style_z: style_z + 1,
                source
            };
        });
    }

};
<commit_msg>move style_z position in tile key (for easier debugging)<commit_after>
const COORD_CHILDREN = {}; // only allocate children coords once per coord

export const TileID = {

    coord(c) {
        return {x: c.x, y: c.y, z: c.z, key: this.coordKey(c)};
    },

    coordKey({x, y, z}) {
        return x + '/' + y + '/' + z;
    },

    key (coords, source, style_z) {
        if (coords.y < 0 || coords.y >= (1 << coords.z) || coords.z < 0) {
            return; // cull tiles out of range (x will wrap)
        }
        return [source.name, coords.x, coords.y, coords.z, style_z].join('/');
    },

    normalizedKey (coords, source, style_z) {
        return this.key(this.normalizedCoord(coords, source), source, style_z);
    },

    normalizedCoord (coords, source) {
        if (source.zoom_bias) {
            coords = this.coordAtZoom(coords, coords.z - source.zoom_bias);
        }
        return this.coordWithMaxZoom(coords, source.max_zoom);
    },

    coordAtZoom({x, y, z}, zoom) {
        zoom = Math.max(0, zoom); // zoom can't go below zero
        if (z !== zoom) {
            let zscale = Math.pow(2, z - zoom);
            x = Math.floor(x / zscale);
            y = Math.floor(y / zscale);
            z = zoom;
        }
        return this.coord({x, y, z});
    },

    coordWithMaxZoom({x, y, z}, max_zoom) {
        if (max_zoom != null && z > max_zoom) {
            return this.coordAtZoom({x, y, z}, max_zoom);
        }
        return this.coord({x, y, z});
    },

    childrenForCoord({x, y, z, key}) {
        if (!COORD_CHILDREN[key]) {
            z++;
            x *= 2;
            y *= 2;
            COORD_CHILDREN[key] = [
                this.coord({x, y,      z}), this.coord({x: x+1, y,      z}),
                this.coord({x, y: y+1, z}), this.coord({x: x+1, y: y+1, z})
            ];
        }
        return COORD_CHILDREN[key];
    },

    isDescendant(parent, descendant) {
        if (descendant.z > parent.z) {
            let {x, y} = this.coordAtZoom(descendant, parent.z);
            return (parent.x === x && parent.y === y);
        }
        return false;
    },

    // Return identifying info for tile's parent tile
    parent ({ coords, source, style_z }) {
        if (style_z > source.max_coord_zoom || style_z <= source.min_coord_zoom) {
            if (style_z > 0) { // no more tiles above style zoom 0
                return {
                    key: this.key(coords, source, style_z - 1),
                    coords,
                    style_z: style_z - 1,
                    source
                };
            }
            return;
        }
        else if (style_z > 0) { // no more tiles above style zoom 0
            const c = this.coordAtZoom(coords, coords.z - 1);
            return {
                key: this.key(c, source, style_z - 1),
                coords: c,
                style_z: style_z - 1,
                source
            };
        }
    },

    // Return identifying info for tile's child tiles
    children ({ coords, source, style_z }) {
        if (style_z >= source.max_coord_zoom || style_z < source.min_coord_zoom) {
            return [{
                key: this.key(coords, source, style_z + 1),
                coords,
                style_z: style_z + 1,
                source
            }];
        }

        const children = this.childrenForCoord(coords);
        return children.map(c => {
            return {
                key: this.key(c, source, style_z + 1),
                coords: c,
                style_z: style_z + 1,
                source
            };
        });
    }

};
<|endoftext|>


<commit_before>"use strict";

/**
* @class Common
*/

const Common = module.exports = {};

Common.injectStyles = function(styles, id) {
  if (document.getElementById(id)) {
    return;
  }

  let root = document.createElement('div');
  root.innerHTML = `<style id="${id}" type="text/css">${styles}</style>`;

  let lastStyle = document.head.querySelector('style:last-of-type');
  Common.domInsertBefore(root.firstElementChild, lastStyle);
};

Common.injectScript = function(url, id, callback) {
  if (document.getElementById(id)) {
    return;
  }

  let script = document.createElement('script');
  script.id = id;
  script.src = url;
  script.onload = callback;

  document.body.appendChild(script);
};

Common.domRemove = function(element) {
  return element.parentElement.removeChild(element);
};

Common.domInsertBefore = function(element, before) {
  return before.parentNode.insertBefore(element, before.previousElementSibling);
};
<commit_msg>fix bug when no style tags exist, closes #3<commit_after>"use strict";

/**
* @class Common
*/

const Common = module.exports = {};

Common.injectStyles = function(styles, id) {
  if (document.getElementById(id)) {
    return;
  }

  let root = document.createElement('div');
  root.innerHTML = `<style id="${id}" type="text/css">${styles}</style>`;

  let lastStyle = document.head.querySelector('style:last-of-type');

  if (lastStyle) {
    Common.domInsertBefore(root.firstElementChild, lastStyle);
  } else {
    document.head.appendChild(root.firstElementChild);
  }
};

Common.injectScript = function(url, id, callback) {
  if (document.getElementById(id)) {
    return;
  }

  let script = document.createElement('script');
  script.id = id;
  script.src = url;
  script.onload = callback;

  document.body.appendChild(script);
};

Common.domRemove = function(element) {
  return element.parentElement.removeChild(element);
};

Common.domInsertBefore = function(element, before) {
  return before.parentNode.insertBefore(element, before.previousElementSibling);
};
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var THREE = require('./three-math.js');

var ROTATE_SPEED = 0.5;
/**
 * Provides a quaternion responsible for pre-panning the scene before further
 * transformations due to device sensors.
 */
function TouchPanner() {
  window.addEventListener('touchstart', this.onTouchStart_.bind(this));
  window.addEventListener('touchmove', this.onTouchMove_.bind(this));
  window.addEventListener('touchend', this.onTouchEnd_.bind(this));

  this.isTouching = false;
  this.rotateStart = new THREE.Vector2();
  this.rotateEnd = new THREE.Vector2();
  this.rotateDelta = new THREE.Vector2();

  this.theta = 0;
  this.orientation = new THREE.Quaternion();
}

TouchPanner.prototype.getOrientation = function() {
  this.orientation.setFromEuler(new THREE.Euler(0, 0, this.theta));
  return this.orientation;
};

TouchPanner.prototype.resetSensor = function() {
  this.theta = 0;
};

TouchPanner.prototype.onTouchStart_ = function(e) {
  // Only respond if there is exactly one touch.
  if (e.touches.length != 1) {
    return;
  }
  this.rotateStart.set(e.touches[0].pageX, e.touches[0].pageY);
  this.isTouching = true;
};

TouchPanner.prototype.onTouchMove_ = function(e) {
  if (!this.isTouching) {
    return;
  }
  this.rotateEnd.set(e.touches[0].pageX, e.touches[0].pageY);
  this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart);
  this.rotateStart.copy(this.rotateEnd);

  var element = document.body;
  this.theta += 2 * Math.PI * this.rotateDelta.x / element.clientWidth * ROTATE_SPEED;
};

TouchPanner.prototype.onTouchEnd_ = function(e) {
  this.isTouching = false;
};

module.exports = TouchPanner;
<commit_msg>Reversed pan direction.<commit_after>/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var THREE = require('./three-math.js');

var ROTATE_SPEED = -0.5;
/**
 * Provides a quaternion responsible for pre-panning the scene before further
 * transformations due to device sensors.
 */
function TouchPanner() {
  window.addEventListener('touchstart', this.onTouchStart_.bind(this));
  window.addEventListener('touchmove', this.onTouchMove_.bind(this));
  window.addEventListener('touchend', this.onTouchEnd_.bind(this));

  this.isTouching = false;
  this.rotateStart = new THREE.Vector2();
  this.rotateEnd = new THREE.Vector2();
  this.rotateDelta = new THREE.Vector2();

  this.theta = 0;
  this.orientation = new THREE.Quaternion();
}

TouchPanner.prototype.getOrientation = function() {
  this.orientation.setFromEuler(new THREE.Euler(0, 0, this.theta));
  return this.orientation;
};

TouchPanner.prototype.resetSensor = function() {
  this.theta = 0;
};

TouchPanner.prototype.onTouchStart_ = function(e) {
  // Only respond if there is exactly one touch.
  if (e.touches.length != 1) {
    return;
  }
  this.rotateStart.set(e.touches[0].pageX, e.touches[0].pageY);
  this.isTouching = true;
};

TouchPanner.prototype.onTouchMove_ = function(e) {
  if (!this.isTouching) {
    return;
  }
  this.rotateEnd.set(e.touches[0].pageX, e.touches[0].pageY);
  this.rotateDelta.subVectors(this.rotateEnd, this.rotateStart);
  this.rotateStart.copy(this.rotateEnd);

  var element = document.body;
  this.theta += 2 * Math.PI * this.rotateDelta.x / element.clientWidth * ROTATE_SPEED;
};

TouchPanner.prototype.onTouchEnd_ = function(e) {
  this.isTouching = false;
};

module.exports = TouchPanner;
<|endoftext|>


<commit_before>define([], function() {
    "use strict"

    const EvalUtils = {

        evalOrError(text) {
            let result
            try {
                result = eval(text)
            } catch (error) {
                result = error
            }
            return result
        },

        eval(text) {
            return eval(text)
        }
    }

    return EvalUtils
})
<commit_msg>Improve EvalUtils to wrap string in parens<commit_after>define([], function() {
    "use strict"

    const EvalUtils = {

        evalOrError(text) {
            let result
            try {
                result = EvalUtils.eval(text)
            } catch (error) {
                result = error
            }
            return result
        },

        eval(text) {
            return eval("(" + text + ")")
        }
    }

    return EvalUtils
})
<|endoftext|>


<commit_before>/**
Copyright (c) 2017 Kenny Do

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**/
import React, {Component} from "react";
import {findDOMNode} from "react-dom";
import {connect} from "react-redux";
import {getHostname, extractMainDomain, getSetting, prepareCookieDomain} from "../../services/libs";
import FilteredExpression from "./components/FilteredExpression";
import {addExpressionUI, cookieCleanupUI, updateSettingUI} from "../UIActions";
import IconButton from "../common_components/IconButton";

class App extends Component {
	constructor(props) {
		super(props);
		this.state = {
			tab: {},
			storeId: ""
		};
	}

	async componentDidMount() {
		const tabs = await browser.tabs.query({
			currentWindow: true, active: true
		});
		this.setState({
			tab: tabs[0],
			storeId: !this.props.contextualIdentities || tabs[0].cookieStoreId === "firefox-default" ? "default" : tabs[0].cookieStoreId
		});
	}

	animateFlash(ref, success) {
		if (ref) {
			let domNode;
			try {
				// eslint-disable-next-line react/no-find-dom-node
				domNode = findDOMNode(ref);
			} catch (e) {
				// Ignore, we just won't animate anything.
			}
			if (domNode) {
				domNode.classList.add(success ? "successAnimated" : "failureAnimated");
				setTimeout(() => {
					domNode.classList.remove(success ? "successAnimated" : "failureAnimated");
				}, 1500);
			}
		}
	}

	async clearCookiesForThisDomain(hostname) {
		const {
			cookieStoreId
		} = this.state.tab;
		const cookies = await browser.cookies.getAll({
			domain: hostname,
			storeId: cookieStoreId
		});
		if (cookies.length > 0) {
			cookies.forEach((cookie) => browser.cookies.remove({
				url: prepareCookieDomain(cookie), name: cookie.name, storeId: cookie.storeId
			}));
			return true;
		}
		return false;
	}

	clearLocalstorageForThisDomain(hostname) {
		// Using this method to ensure cross browser compatiblity
		browser.tabs.executeScript({
			code: "window.localStorage.clear();window.sessionStorage.clear();",
			allFrames: true
		});
		return true;
	}

	render() {
		const {
			tab, storeId
		} = this.state;
		const {
			onNewExpression, onCookieCleanup, onUpdateSetting, contextualIdentities, cache, settings
		} = this.props;
		const hostname = getHostname(tab.url);
		const mainDomain = extractMainDomain(hostname);
		const addableHostnames = [
			hostname === mainDomain ? undefined : `*.${mainDomain}`,
			hostname
		].filter(Boolean);
		if (hostname !== "") {
			addableHostnames.push(`*.${hostname}`);
		}
		return (

				<div
					className="row"
					style={{
						paddingTop: "8px",
						paddingBottom: "8px",
						backgroundColor: "rgba(0, 0, 0, 0.05)",
						borderBottom: "1px solid rgba(0, 0, 0, 0.1)",
						alignItems: "center",
						justifyContent: "space-between",
						minWidth: `${cache.browserDetect === "Chrome" ? "750px" : ""}`
					}}
				>

						<IconButton
							iconName="power-off"
							className={settings.activeMode.value ? "btn-success" : "btn-danger"}
							style={{
								margin: "0 4px"
							}}
							onClick={() => onUpdateSetting({
								...settings.activeMode, value: !settings.activeMode.value
							})}
							title={settings.activeMode.value ? browser.i18n.getMessage("disableAutoDeleteText") : browser.i18n.getMessage("enableAutoDeleteText")}
							text={settings.activeMode.value ? browser.i18n.getMessage("autoDeleteEnabledText") : browser.i18n.getMessage("autoDeleteDisabledText")}
						/>

 {this.cleanButtonContainerRef = e;}}
							style={{
								margin: "0 4px"
							}}
						>
							<IconButton
								iconName="eraser"
								className="btn-warning"
								onClick={() => {
									onCookieCleanup({
										greyCleanup: false, ignoreOpenTabs: false
									});
									this.animateFlash(this.cleanButtonContainerRef, true);
								}}
								title={browser.i18n.getMessage("cookieCleanupText")}
								text={browser.i18n.getMessage("cleanText")}
							/>

							<button className="btn btn-warning dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"/>

								 {
										onCookieCleanup({
											greyCleanup: false, ignoreOpenTabs: true
										});
										this.animateFlash(this.cleanButtonContainerRef, true);
									}}
									title={browser.i18n.getMessage("cookieCleanupIgnoreOpenTabsText")}
								>
									{browser.i18n.getMessage("cleanIgnoringOpenTabsText")}

								 {
										const success = await this.clearCookiesForThisDomain(hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["cookies", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["cookies"])}

								 {
										const success = await this.clearLocalstorageForThisDomain(hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["localstorage", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["localstorage"])}

						<IconButton
							iconName="cog"
							className="btn-info"
							style={{
								margin: "0 4px"
							}}
							onClick={() => browser.runtime.openOptionsPage()}
							title={browser.i18n.getMessage("preferencesText")}
							text={browser.i18n.getMessage("preferencesText")}
						/>

					{tab.favIconUrl &&

					}

						{
							// Temporary fix until contextualIdentities events land
						}
						{!contextualIdentities ? `${hostname}` : `${hostname} ${cache[storeId] !== undefined ? `(${cache[storeId]})` : ""}`}

				{addableHostnames.map((hostname) => (

{hostname}

							<IconButton
								className="btn-secondary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "GREY", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toGreyListText")}
								text={browser.i18n.getMessage("greyListWordText")}
							/>

							<IconButton
								className="btn-primary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "WHITE", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toWhiteListText")}
								text={browser.i18n.getMessage("whiteListWordText")}
							/>

				))}

					<FilteredExpression url={hostname} storeId={storeId}/>

		);
	}
}

const mapStateToProps = (state) => {
	const {
		cache, settings
	} = state;
	return {
		contextualIdentities: getSetting(state, "contextualIdentities"), cache, settings
	};
};

const mapDispatchToProps = (dispatch) => (
	{
		onUpdateSetting(newSetting) {
			dispatch(
				updateSettingUI(newSetting)
			);
		},
		onNewExpression(payload) {
			dispatch(
				addExpressionUI(payload)
			);
		},
		onCookieCleanup(payload) {
			dispatch(
				cookieCleanupUI(payload)
			);
		}
	});

export default connect(mapStateToProps, mapDispatchToProps)(App);
<commit_msg>Fix clear all cookies for this domain for #75<commit_after>/**
Copyright (c) 2017 Kenny Do

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**/
import React, {Component} from "react";
import {findDOMNode} from "react-dom";
import {connect} from "react-redux";
import {getHostname, extractMainDomain, getSetting, prepareCookieDomain, returnOptionalCookieAPIAttributes} from "../../services/libs";
import FilteredExpression from "./components/FilteredExpression";
import {addExpressionUI, cookieCleanupUI, updateSettingUI} from "../UIActions";
import IconButton from "../common_components/IconButton";

class App extends Component {
	constructor(props) {
		super(props);
		this.state = {
			tab: {},
			storeId: ""
		};
	}

	async componentDidMount() {
		const tabs = await browser.tabs.query({
			currentWindow: true, active: true
		});
		this.setState({
			tab: tabs[0],
			storeId: !this.props.contextualIdentities || tabs[0].cookieStoreId === "firefox-default" ? "default" : tabs[0].cookieStoreId
		});
	}

	animateFlash(ref, success) {
		if (ref) {
			let domNode;
			try {
				// eslint-disable-next-line react/no-find-dom-node
				domNode = findDOMNode(ref);
			} catch (e) {
				// Ignore, we just won't animate anything.
			}
			if (domNode) {
				domNode.classList.add(success ? "successAnimated" : "failureAnimated");
				setTimeout(() => {
					domNode.classList.remove(success ? "successAnimated" : "failureAnimated");
				}, 1500);
			}
		}
	}

	async clearCookiesForThisDomain(cache, hostname) {
		const {
			cookieStoreId
		} = this.state.tab;
		const cookies = await browser.cookies.getAll(
			returnOptionalCookieAPIAttributes({cache}, {
				domain: hostname,
				storeId: cookieStoreId,
				firstPartyDomain: hostname
			})
		);

		if (cookies.length > 0) {
			cookies.forEach((cookie) => browser.cookies.remove(
				returnOptionalCookieAPIAttributes({cache}, {
					url: prepareCookieDomain(cookie),
					name: cookie.name,
					storeId: cookie.storeId,
					firstPartyDomain: cookie.firstPartyDomain
				})
			)
		);
			return true;
		}
		return false;
	}

	clearLocalstorageForThisDomain(hostname) {
		// Using this method to ensure cross browser compatiblity
		browser.tabs.executeScript({
			code: "window.localStorage.clear();window.sessionStorage.clear();",
			allFrames: true
		});
		return true;
	}

	render() {
		const {
			tab, storeId
		} = this.state;
		const {
			onNewExpression, onCookieCleanup, onUpdateSetting, contextualIdentities, cache, settings
		} = this.props;
		const hostname = getHostname(tab.url);
		const mainDomain = extractMainDomain(hostname);
		const addableHostnames = [
			hostname === mainDomain ? undefined : `*.${mainDomain}`,
			hostname
		].filter(Boolean);
		if (hostname !== "") {
			addableHostnames.push(`*.${hostname}`);
		}
		return (

				<div
					className="row"
					style={{
						paddingTop: "8px",
						paddingBottom: "8px",
						backgroundColor: "rgba(0, 0, 0, 0.05)",
						borderBottom: "1px solid rgba(0, 0, 0, 0.1)",
						alignItems: "center",
						justifyContent: "space-between",
						minWidth: `${cache.browserDetect === "Chrome" ? "750px" : ""}`
					}}
				>

						<IconButton
							iconName="power-off"
							className={settings.activeMode.value ? "btn-success" : "btn-danger"}
							style={{
								margin: "0 4px"
							}}
							onClick={() => onUpdateSetting({
								...settings.activeMode, value: !settings.activeMode.value
							})}
							title={settings.activeMode.value ? browser.i18n.getMessage("disableAutoDeleteText") : browser.i18n.getMessage("enableAutoDeleteText")}
							text={settings.activeMode.value ? browser.i18n.getMessage("autoDeleteEnabledText") : browser.i18n.getMessage("autoDeleteDisabledText")}
						/>

 {this.cleanButtonContainerRef = e;}}
							style={{
								margin: "0 4px"
							}}
						>
							<IconButton
								iconName="eraser"
								className="btn-warning"
								onClick={() => {
									onCookieCleanup({
										greyCleanup: false, ignoreOpenTabs: false
									});
									this.animateFlash(this.cleanButtonContainerRef, true);
								}}
								title={browser.i18n.getMessage("cookieCleanupText")}
								text={browser.i18n.getMessage("cleanText")}
							/>

							<button className="btn btn-warning dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"/>

								 {
										onCookieCleanup({
											greyCleanup: false, ignoreOpenTabs: true
										});
										this.animateFlash(this.cleanButtonContainerRef, true);
									}}
									title={browser.i18n.getMessage("cookieCleanupIgnoreOpenTabsText")}
								>
									{browser.i18n.getMessage("cleanIgnoringOpenTabsText")}

								 {
										const success = await this.clearCookiesForThisDomain(cache, hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["cookies", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["cookies"])}

								 {
										const success = await this.clearLocalstorageForThisDomain(hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["localstorage", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["localstorage"])}

						<IconButton
							iconName="cog"
							className="btn-info"
							style={{
								margin: "0 4px"
							}}
							onClick={() => browser.runtime.openOptionsPage()}
							title={browser.i18n.getMessage("preferencesText")}
							text={browser.i18n.getMessage("preferencesText")}
						/>

					{tab.favIconUrl &&

					}

						{
							// Temporary fix until contextualIdentities events land
						}
						{!contextualIdentities ? `${hostname}` : `${hostname} ${cache[storeId] !== undefined ? `(${cache[storeId]})` : ""}`}

				{addableHostnames.map((hostname) => (

{hostname}

							<IconButton
								className="btn-secondary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "GREY", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toGreyListText")}
								text={browser.i18n.getMessage("greyListWordText")}
							/>

							<IconButton
								className="btn-primary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "WHITE", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toWhiteListText")}
								text={browser.i18n.getMessage("whiteListWordText")}
							/>

				))}

					<FilteredExpression url={hostname} storeId={storeId}/>

		);
	}
}

const mapStateToProps = (state) => {
	const {
		cache, settings
	} = state;
	return {
		contextualIdentities: getSetting(state, "contextualIdentities"), cache, settings
	};
};

const mapDispatchToProps = (dispatch) => (
	{
		onUpdateSetting(newSetting) {
			dispatch(
				updateSettingUI(newSetting)
			);
		},
		onNewExpression(payload) {
			dispatch(
				addExpressionUI(payload)
			);
		},
		onCookieCleanup(payload) {
			dispatch(
				cookieCleanupUI(payload)
			);
		}
	});

export default connect(mapStateToProps, mapDispatchToProps)(App);
<|endoftext|>


<commit_before>/**
Copyright (c) 2017 Kenny Do

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**/
import React, {Component} from "react";
import {findDOMNode} from "react-dom";
import {connect} from "react-redux";
import {getHostname, extractMainDomain, getSetting, prepareCookieDomain, returnOptionalCookieAPIAttributes, isAnIP} from "../../services/libs";
import FilteredExpression from "./components/FilteredExpression";
import {addExpressionUI, cookieCleanupUI, updateSettingUI} from "../UIActions";
import IconButton from "../common_components/IconButton";

class App extends Component {
	constructor(props) {
		super(props);
		this.state = {
			tab: {},
			storeId: ""
		};
	}

	async componentDidMount() {
		const tabs = await browser.tabs.query({
			currentWindow: true, active: true
		});
		this.setState({
			tab: tabs[0],
			storeId: !this.props.contextualIdentities || tabs[0].cookieStoreId === "firefox-default" ? "default" : tabs[0].cookieStoreId
		});
	}

	animateFlash(ref, success) {
		if (ref) {
			let domNode;
			try {
				// eslint-disable-next-line react/no-find-dom-node
				domNode = findDOMNode(ref);
			} catch (e) {
				// Ignore, we just won't animate anything.
			}
			if (domNode) {
				domNode.classList.add(success ? "successAnimated" : "failureAnimated");
				setTimeout(() => {
					domNode.classList.remove(success ? "successAnimated" : "failureAnimated");
				}, 1500);
			}
		}
	}

	async clearCookiesForThisDomain(cache, hostname) {
		const {
			cookieStoreId
		} = this.state.tab;
		const cookies = await browser.cookies.getAll(
			returnOptionalCookieAPIAttributes({
				cache
			}, {
				domain: hostname,
				storeId: cookieStoreId,
				firstPartyDomain: hostname
			})
		);

		if (cookies.length > 0) {
			cookies.forEach((cookie) => browser.cookies.remove(
				returnOptionalCookieAPIAttributes({
					cache
				}, {
					url: prepareCookieDomain(cookie),
					name: cookie.name,
					storeId: cookie.storeId,
					firstPartyDomain: cookie.firstPartyDomain
				})
			)
			);
			return true;
		}
		return false;
	}

	clearLocalstorageForThisDomain(hostname) {
		// Using this method to ensure cross browser compatiblity
		browser.tabs.executeScript({
			code: "window.localStorage.clear();window.sessionStorage.clear();",
			allFrames: true
		});
		return true;
	}

	render() {
		const {
			tab, storeId
		} = this.state;
		const {
			onNewExpression, onCookieCleanup, onUpdateSetting, contextualIdentities, cache, settings
		} = this.props;
		const hostname = getHostname(tab.url);
		const mainDomain = extractMainDomain(hostname);
		const addableHostnames = [
			hostname === mainDomain ? undefined : `*.${mainDomain}`,
			hostname
		].filter(Boolean);
		if (hostname !== "" && !isAnIP(tab.url)) {
			addableHostnames.push(`*.${hostname}`);
		}
		return (

				<div
					className="row"
					style={{
						paddingTop: "8px",
						paddingBottom: "8px",
						backgroundColor: "rgba(0, 0, 0, 0.05)",
						borderBottom: "1px solid rgba(0, 0, 0, 0.1)",
						alignItems: "center",
						justifyContent: "space-between",
						minWidth: `${cache.browserDetect === "Chrome" ? "750px" : ""}`
					}}
				>
					{
						window.innerWidth > 350 &&

					}

						<IconButton
							iconName="power-off"
							className={settings.activeMode.value ? "btn-success" : "btn-danger"}
							style={{
								margin: "0 4px"
							}}
							onClick={() => onUpdateSetting({
								...settings.activeMode, value: !settings.activeMode.value
							})}
							title={settings.activeMode.value ? browser.i18n.getMessage("disableAutoDeleteText") : browser.i18n.getMessage("enableAutoDeleteText")}
							text={settings.activeMode.value ? browser.i18n.getMessage("autoDeleteEnabledText") : browser.i18n.getMessage("autoDeleteDisabledText")}
						/>

						<IconButton
							iconName="bell"
							className={settings.showNotificationAfterCleanup.value ? "btn-success" : "btn-danger"}
							style={{
								margin: "0 4px"
							}}
							onClick={() => onUpdateSetting({
								...settings.showNotificationAfterCleanup, value: !settings.showNotificationAfterCleanup.value
							})}
							title={browser.i18n.getMessage("toggleNotificationText")}
							text={settings.showNotificationAfterCleanup.value ? browser.i18n.getMessage("notificationEnabledText") : browser.i18n.getMessage("notificationDisabledText")}
						/>

 {this.cleanButtonContainerRef = e;}}
							style={{
								margin: "0 4px"
							}}
						>
							<IconButton
								iconName="eraser"
								className="btn-warning"
								onClick={() => {
									onCookieCleanup({
										greyCleanup: false, ignoreOpenTabs: false
									});
									this.animateFlash(this.cleanButtonContainerRef, true);
								}}
								title={browser.i18n.getMessage("cookieCleanupText")}
								text={browser.i18n.getMessage("cleanText")}
							/>

							<button className="btn btn-warning dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"/>

								 {
										onCookieCleanup({
											greyCleanup: false, ignoreOpenTabs: true
										});
										this.animateFlash(this.cleanButtonContainerRef, true);
									}}
									title={browser.i18n.getMessage("cookieCleanupIgnoreOpenTabsText")}
								>
									{browser.i18n.getMessage("cleanIgnoringOpenTabsText")}

								 {
										const success = await this.clearCookiesForThisDomain(cache, hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["cookies", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["cookies"])}

								 {
										const success = await this.clearLocalstorageForThisDomain(hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["localstorage", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["localstorage"])}

						<IconButton
							iconName="cog"
							className="btn-info"
							style={{
								margin: "0 4px"
							}}
							onClick={() => browser.tabs.create({
								url: "/settings/settings.html#tabSettings"
							})}
							title={browser.i18n.getMessage("preferencesText")}
							text={browser.i18n.getMessage("preferencesText")}
						/>

					{tab.favIconUrl &&

					}

						{
							// Temporary fix until contextualIdentities events land
						}
						{!contextualIdentities ? `${hostname}` : `${hostname} ${cache[storeId] !== undefined ? `(${cache[storeId]})` : ""}`}

				{addableHostnames.map((hostname) => (

{hostname}

							<IconButton
								className="btn-secondary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "GREY", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toGreyListText")}
								text={browser.i18n.getMessage("greyListWordText")}
							/>

							<IconButton
								className="btn-primary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "WHITE", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toWhiteListText")}
								text={browser.i18n.getMessage("whiteListWordText")}
							/>

				))}

					<FilteredExpression url={hostname} storeId={storeId}/>

		);
	}
}

const mapStateToProps = (state) => {
	const {
		cache, settings
	} = state;
	return {
		contextualIdentities: getSetting(state, "contextualIdentities"), cache, settings
	};
};

const mapDispatchToProps = (dispatch) => (
	{
		onUpdateSetting(newSetting) {
			dispatch(
				updateSettingUI(newSetting)
			);
		},
		onNewExpression(payload) {
			dispatch(
				addExpressionUI(payload)
			);
		},
		onCookieCleanup(payload) {
			dispatch(
				cookieCleanupUI(payload)
			);
		}
	});

export default connect(mapStateToProps, mapDispatchToProps)(App);
<commit_msg>Close popup when opening settings page (#331)<commit_after>/**
Copyright (c) 2017 Kenny Do

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
**/
import React, {Component} from "react";
import {findDOMNode} from "react-dom";
import {connect} from "react-redux";
import {getHostname, extractMainDomain, getSetting, prepareCookieDomain, returnOptionalCookieAPIAttributes, isAnIP} from "../../services/libs";
import FilteredExpression from "./components/FilteredExpression";
import {addExpressionUI, cookieCleanupUI, updateSettingUI} from "../UIActions";
import IconButton from "../common_components/IconButton";

class App extends Component {
	constructor(props) {
		super(props);
		this.state = {
			tab: {},
			storeId: ""
		};
	}

	async componentDidMount() {
		const tabs = await browser.tabs.query({
			currentWindow: true, active: true
		});
		this.setState({
			tab: tabs[0],
			storeId: !this.props.contextualIdentities || tabs[0].cookieStoreId === "firefox-default" ? "default" : tabs[0].cookieStoreId
		});
	}

	animateFlash(ref, success) {
		if (ref) {
			let domNode;
			try {
				// eslint-disable-next-line react/no-find-dom-node
				domNode = findDOMNode(ref);
			} catch (e) {
				// Ignore, we just won't animate anything.
			}
			if (domNode) {
				domNode.classList.add(success ? "successAnimated" : "failureAnimated");
				setTimeout(() => {
					domNode.classList.remove(success ? "successAnimated" : "failureAnimated");
				}, 1500);
			}
		}
	}

	async clearCookiesForThisDomain(cache, hostname) {
		const {
			cookieStoreId
		} = this.state.tab;
		const cookies = await browser.cookies.getAll(
			returnOptionalCookieAPIAttributes({
				cache
			}, {
				domain: hostname,
				storeId: cookieStoreId,
				firstPartyDomain: hostname
			})
		);

		if (cookies.length > 0) {
			cookies.forEach((cookie) => browser.cookies.remove(
				returnOptionalCookieAPIAttributes({
					cache
				}, {
					url: prepareCookieDomain(cookie),
					name: cookie.name,
					storeId: cookie.storeId,
					firstPartyDomain: cookie.firstPartyDomain
				})
			)
			);
			return true;
		}
		return false;
	}

	clearLocalstorageForThisDomain(hostname) {
		// Using this method to ensure cross browser compatiblity
		browser.tabs.executeScript({
			code: "window.localStorage.clear();window.sessionStorage.clear();",
			allFrames: true
		});
		return true;
	}

	render() {
		const {
			tab, storeId
		} = this.state;
		const {
			onNewExpression, onCookieCleanup, onUpdateSetting, contextualIdentities, cache, settings
		} = this.props;
		const hostname = getHostname(tab.url);
		const mainDomain = extractMainDomain(hostname);
		const addableHostnames = [
			hostname === mainDomain ? undefined : `*.${mainDomain}`,
			hostname
		].filter(Boolean);
		if (hostname !== "" && !isAnIP(tab.url)) {
			addableHostnames.push(`*.${hostname}`);
		}
		return (

				<div
					className="row"
					style={{
						paddingTop: "8px",
						paddingBottom: "8px",
						backgroundColor: "rgba(0, 0, 0, 0.05)",
						borderBottom: "1px solid rgba(0, 0, 0, 0.1)",
						alignItems: "center",
						justifyContent: "space-between",
						minWidth: `${cache.browserDetect === "Chrome" ? "750px" : ""}`
					}}
				>
					{
						window.innerWidth > 350 &&

					}

						<IconButton
							iconName="power-off"
							className={settings.activeMode.value ? "btn-success" : "btn-danger"}
							style={{
								margin: "0 4px"
							}}
							onClick={() => onUpdateSetting({
								...settings.activeMode, value: !settings.activeMode.value
							})}
							title={settings.activeMode.value ? browser.i18n.getMessage("disableAutoDeleteText") : browser.i18n.getMessage("enableAutoDeleteText")}
							text={settings.activeMode.value ? browser.i18n.getMessage("autoDeleteEnabledText") : browser.i18n.getMessage("autoDeleteDisabledText")}
						/>

						<IconButton
							iconName="bell"
							className={settings.showNotificationAfterCleanup.value ? "btn-success" : "btn-danger"}
							style={{
								margin: "0 4px"
							}}
							onClick={() => onUpdateSetting({
								...settings.showNotificationAfterCleanup, value: !settings.showNotificationAfterCleanup.value
							})}
							title={browser.i18n.getMessage("toggleNotificationText")}
							text={settings.showNotificationAfterCleanup.value ? browser.i18n.getMessage("notificationEnabledText") : browser.i18n.getMessage("notificationDisabledText")}
						/>

 {this.cleanButtonContainerRef = e;}}
							style={{
								margin: "0 4px"
							}}
						>
							<IconButton
								iconName="eraser"
								className="btn-warning"
								onClick={() => {
									onCookieCleanup({
										greyCleanup: false, ignoreOpenTabs: false
									});
									this.animateFlash(this.cleanButtonContainerRef, true);
								}}
								title={browser.i18n.getMessage("cookieCleanupText")}
								text={browser.i18n.getMessage("cleanText")}
							/>

							<button className="btn btn-warning dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"/>

								 {
										onCookieCleanup({
											greyCleanup: false, ignoreOpenTabs: true
										});
										this.animateFlash(this.cleanButtonContainerRef, true);
									}}
									title={browser.i18n.getMessage("cookieCleanupIgnoreOpenTabsText")}
								>
									{browser.i18n.getMessage("cleanIgnoringOpenTabsText")}

								 {
										const success = await this.clearCookiesForThisDomain(cache, hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["cookies", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["cookies"])}

								 {
										const success = await this.clearLocalstorageForThisDomain(hostname);
										this.animateFlash(this.cleanButtonContainerRef, success);
									}}
									title={browser.i18n.getMessage("clearSiteDataForDomainText", ["localstorage", hostname])}
								>
									{browser.i18n.getMessage("clearSiteDataText", ["localstorage"])}

						<IconButton
							iconName="cog"
							className="btn-info"
							style={{
								margin: "0 4px"
							}}
							onClick={() => {
								browser.tabs.create({
									url: "/settings/settings.html#tabSettings"
								});
								window.close();
							}}
							title={browser.i18n.getMessage("preferencesText")}
							text={browser.i18n.getMessage("preferencesText")}
						/>

					{tab.favIconUrl &&

					}

						{
							// Temporary fix until contextualIdentities events land
						}
						{!contextualIdentities ? `${hostname}` : `${hostname} ${cache[storeId] !== undefined ? `(${cache[storeId]})` : ""}`}

				{addableHostnames.map((hostname) => (

{hostname}

							<IconButton
								className="btn-secondary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "GREY", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toGreyListText")}
								text={browser.i18n.getMessage("greyListWordText")}
							/>

							<IconButton
								className="btn-primary"
								onClick={() => {onNewExpression({
									expression: hostname, listType: "WHITE", storeId
								});}}
								iconName="plus"
								title={browser.i18n.getMessage("toWhiteListText")}
								text={browser.i18n.getMessage("whiteListWordText")}
							/>

				))}

					<FilteredExpression url={hostname} storeId={storeId}/>

		);
	}
}

const mapStateToProps = (state) => {
	const {
		cache, settings
	} = state;
	return {
		contextualIdentities: getSetting(state, "contextualIdentities"), cache, settings
	};
};

const mapDispatchToProps = (dispatch) => (
	{
		onUpdateSetting(newSetting) {
			dispatch(
				updateSettingUI(newSetting)
			);
		},
		onNewExpression(payload) {
			dispatch(
				addExpressionUI(payload)
			);
		},
		onCookieCleanup(payload) {
			dispatch(
				cookieCleanupUI(payload)
			);
		}
	});

export default connect(mapStateToProps, mapDispatchToProps)(App);
<|endoftext|>


<commit_before>'use strict';

const docker = require('./util/dockercmd');
const log = require('./util/log');
const readConfig = require('./readconfig');
const convo = require('./convo');
const MsgQueue = require('./msgqueue');

const request = require('request');
const Promise = require('bluebird');
const async = require('async');
const url = require('url');
const tcpPortUsed = require('tcp-port-used');
const io = require('socket.io-client');
const _ = require('lodash');

var channelIdDefault = randomInt(1000000000, 9999999999);

function randomInt(low, high) {
  return Math.floor(Math.random() * (high - low) + low);
}

var config = { };
var socket = null;
var msgqueue = null;

function beforeAll(configToSet) {
  return new Promise(function(beforeAllResolve, beforeAllReject) {

    async.series([

      function(readConfigDone) {
        readConfig.readAndMergeConfig(configToSet).then(function(resolvedConfig) {
          config = resolvedConfig;
          readConfigDone();
        }).catch(function(err) {
          readConfigDone(err);
        });
      },

      function(dockerImageReady) {
        log.debug(JSON.stringify(config, null, 2));
        docker.setupContainer(config).then(function() {
          dockerImageReady();
        }).catch(function(err) {
          dockerImageReady(err);
        });
      }

     ],
    function(err) {
      if (err)
        beforeAllReject(err);
      else
        beforeAllResolve(config);
    });
  });

}

function afterAll() {
  return new Promise(function(afterAllResolve, afterAllReject) {
    async.series([

      function(teardownContainerDone) {
        docker.teardownContainer().then(function() {
          teardownContainerDone();
        }).catch(function(err) {
          teardownContainerDone(err);
        });
      }
    ],
    function(err) {
      if (err)
        afterAllReject(err);
      else
        afterAllResolve();
    });
  });
}

function beforeEach() {
  return new Promise(function(beforeEachResolve, beforeEachReject) {

    async.series([

      function(startMockupsDone) {
        docker.startContainer((spec) => spec.imagename !== 'testmybot').then(function() {
          startMockupsDone();
        }).catch(function(err) {
          startMockupsDone(err);
        });
      },

      function(mockupOnline) {
        var urlparts = url.parse(config.testendpoint);

        var online = false;
        async.until(
          () => online,
          (callback) => {
            log.debug('checking port usage (' + config.testendpoint + ') before proceed (to have mocks online)');

            tcpPortUsed.check(parseInt(urlparts.port), urlparts.hostname)
            .then(function(inUse) {
                log.debug('port usage (' + config.testendpoint + '): ' + inUse);
                if (inUse) {
                  online = true;
                  callback();
                } else {
                  setTimeout(callback, 2000);
                }
            }, function(err) {
              log.warn('error on port check: ' + err);
              setTimeout(callback, 2000);
            });
          },
          (err) => mockupOnline(err)
        );
      },

      function(startContainerDone) {
        docker.startContainer((spec) => spec.imagename === 'testmybot').then(function() {
          startContainerDone();
        }).catch(function(err) {
          startContainerDone(err);
        });
      },

      function(startupPhaseDone) {
        if (config.startupphase) {
          setTimeout(startupPhaseDone, config.startupphase);
        } else {
          startupPhaseDone();
        }
      },

      function(endpointOnline) {
        var online = false;
        async.until(
          () => online,
          (callback) => {
            var options = {
              uri: config.testendpoint,
              method: 'GET'
            };
            log.debug('checking if chatbot (testmybot) is online ...');
            request(options, function (err, response, body) {
              if (err) {
                setTimeout(callback, 2000);
              } else if (response && response.statusCode === 200) {
                log.debug('chatbot (testmybot) is online!');
                online = true;
                callback();
              } else {
                setTimeout(callback, 2000);
              }
            });
          },
          (err) => endpointOnline(err)
        );
      },

      function(socketStartDone) {

        if (socket) {
          socket.disconnect();
          socket = null;
        }

        msgqueue = new MsgQueue();

        socket = io.connect(config.testendpoint);
        socket.on('botsays', function (saysContent) {
          log.debug('socket received botsays event ' + JSON.stringify(saysContent));
          if (saysContent && msgqueue) {
            msgqueue.push(saysContent);
          }
        });
        socket.on('error', function(err) {
          log.error('socket connection error! ' + err);
        });
        socketStartDone();
      }

    ],
    function(err) {
      if (err)
        beforeEachReject(err);
      else
        beforeEachResolve();
    });
  });
}

function afterEach() {
  return new Promise(function(afterEachResolve, afterEachReject) {

    async.series([

      function(socketStopDone) {
        if (socket) {
          socket.disconnect();
          socket = null;
        }
        msgqueue = null;
        socketStopDone();
      },

      function(stopContainerDone) {
        docker.stopContainer().then(function() {
          stopContainerDone();
        }).catch(function(err) {
          stopContainerDone(err);
        });
      }
    ],
    function(err) {
      if (err)
        afterEachReject(err);
      else
        afterEachResolve();
    });
  });
}

function hears(msg, channelId) {
  if (!channelId) channelId = channelIdDefault;

  return new Promise(function(hearsResolve, hearsReject) {
    if (socket) {
      socket.emit('bothears', channelId, msg);
      hearsResolve();
    } else {
      hearsReject('Socket not online');
    }
  });
}

function says(channelId, timeoutMillis) {
  if (!channelId) channelId = channelIdDefault;

  return new Promise(function(saysResolve, saysReject) {

    if (!timeoutMillis)
      timeoutMillis = config.defaultsaytimeout;

    var timeoutRequest = async.timeout(function(callback) {
      msgqueue.registerListener(
        (msg) => {
          callback(null, msg);
        },
        channelId);
    }, timeoutMillis);

    timeoutRequest(function(err, body) {
      if (err && err.code === 'ETIMEDOUT') {
        saysReject('nothing said in time');
      } else if (err) {
        saysReject('says error: ' + err);
      } else {
        saysResolve(body);
      }
    });
  });
}

function setupTestSuite(testcaseCb, assertCb, failCb) {

  var testcaseFiles = convo.getConvoFilesSync();

  testcaseFiles.forEach(function(testcaseFile) {
    log.info('adding test case file ' + testcaseFile);

    testcaseCb(testcaseFile, function(testcaseDone) {
      log.info('running testcase ' + testcaseFile);

      convo.readConvo(testcaseFile).then(
        (testcase) => {

          async.eachSeries(testcase.conversation,
            (convomsg, convomsgDone) => {

              if (convomsg.from === 'me') {
                log.debug(testcase.name + ': hears ' + convomsg.msg);
                hears(convomsg.msg).then(convomsgDone).catch(convomsgDone);
              } else if (convomsg.from === 'bot') {
                log.debug(testcase.name + ': wait for says ');
                says().then((saysmsg) => {
                  if (saysmsg.messageText) {
                    log.debug(testcase.name + ': says ' + saysmsg.messageText);
                    assertCb(saysmsg.messageText, convomsg.msg);
                  } else {
                    log.debug(testcase.name + ': says ' + JSON.stringify(saysmsg.message));
                    assertCb(JSON.stringify(saysmsg.message), JSON.stringify(convomsg.msg));
                  }
                  convomsgDone();
                }).catch((err) => {
                  convomsgDone(err);
                });
              }
            },
            (err) => {
              if (err) {
                log.info(testcase.name + ' failed: ' + err);
                failCb(err);
              }
              log.info(testcase.name + ' ready, calling done function.');
              testcaseDone();
            });

        },
        (err) => {
          failCb(err);
        });
    });
  });
}

module.exports = {
  beforeAll: beforeAll,
  afterAll: afterAll,
  beforeEach : beforeEach,
  afterEach: afterEach,
  setupTestSuite: setupTestSuite,
  hears: hears,
  says: says,

};<commit_msg>matching structured messages<commit_after>'use strict';

const docker = require('./util/dockercmd');
const log = require('./util/log');
const readConfig = require('./readconfig');
const convo = require('./convo');
const MsgQueue = require('./msgqueue');

const request = require('request');
const Promise = require('bluebird');
const async = require('async');
const url = require('url');
const tcpPortUsed = require('tcp-port-used');
const io = require('socket.io-client');
const _ = require('lodash');

var channelIdDefault = randomInt(1000000000, 9999999999);

function randomInt(low, high) {
  return Math.floor(Math.random() * (high - low) + low);
}

var config = { };
var socket = null;
var msgqueue = null;

function beforeAll(configToSet) {
  return new Promise(function(beforeAllResolve, beforeAllReject) {

    async.series([

      function(readConfigDone) {
        readConfig.readAndMergeConfig(configToSet).then(function(resolvedConfig) {
          config = resolvedConfig;
          readConfigDone();
        }).catch(function(err) {
          readConfigDone(err);
        });
      },

      function(dockerImageReady) {
        log.debug(JSON.stringify(config, null, 2));
        docker.setupContainer(config).then(function() {
          dockerImageReady();
        }).catch(function(err) {
          dockerImageReady(err);
        });
      }

     ],
    function(err) {
      if (err)
        beforeAllReject(err);
      else
        beforeAllResolve(config);
    });
  });

}

function afterAll() {
  return new Promise(function(afterAllResolve, afterAllReject) {
    async.series([

      function(teardownContainerDone) {
        docker.teardownContainer().then(function() {
          teardownContainerDone();
        }).catch(function(err) {
          teardownContainerDone(err);
        });
      }
    ],
    function(err) {
      if (err)
        afterAllReject(err);
      else
        afterAllResolve();
    });
  });
}

function beforeEach() {
  return new Promise(function(beforeEachResolve, beforeEachReject) {

    async.series([

      function(startMockupsDone) {
        docker.startContainer((spec) => spec.imagename !== 'testmybot').then(function() {
          startMockupsDone();
        }).catch(function(err) {
          startMockupsDone(err);
        });
      },

      function(mockupOnline) {
        var urlparts = url.parse(config.testendpoint);

        var online = false;
        async.until(
          () => online,
          (callback) => {
            log.debug('checking port usage (' + config.testendpoint + ') before proceed (to have mocks online)');

            tcpPortUsed.check(parseInt(urlparts.port), urlparts.hostname)
            .then(function(inUse) {
                log.debug('port usage (' + config.testendpoint + '): ' + inUse);
                if (inUse) {
                  online = true;
                  callback();
                } else {
                  setTimeout(callback, 2000);
                }
            }, function(err) {
              log.warn('error on port check: ' + err);
              setTimeout(callback, 2000);
            });
          },
          (err) => mockupOnline(err)
        );
      },

      function(startContainerDone) {
        docker.startContainer((spec) => spec.imagename === 'testmybot').then(function() {
          startContainerDone();
        }).catch(function(err) {
          startContainerDone(err);
        });
      },

      function(startupPhaseDone) {
        if (config.startupphase) {
          setTimeout(startupPhaseDone, config.startupphase);
        } else {
          startupPhaseDone();
        }
      },

      function(endpointOnline) {
        var online = false;
        async.until(
          () => online,
          (callback) => {
            var options = {
              uri: config.testendpoint,
              method: 'GET'
            };
            log.debug('checking if chatbot (testmybot) is online ...');
            request(options, function (err, response, body) {
              if (err) {
                setTimeout(callback, 2000);
              } else if (response && response.statusCode === 200) {
                log.debug('chatbot (testmybot) is online!');
                online = true;
                callback();
              } else {
                setTimeout(callback, 2000);
              }
            });
          },
          (err) => endpointOnline(err)
        );
      },

      function(socketStartDone) {

        if (socket) {
          socket.disconnect();
          socket = null;
        }

        msgqueue = new MsgQueue();

        socket = io.connect(config.testendpoint);
        socket.on('botsays', function (saysContent) {
          log.debug('socket received botsays event ' + JSON.stringify(saysContent));
          if (saysContent && msgqueue) {
            msgqueue.push(saysContent);
          }
        });
        socket.on('error', function(err) {
          log.error('socket connection error! ' + err);
        });
        socketStartDone();
      }

    ],
    function(err) {
      if (err)
        beforeEachReject(err);
      else
        beforeEachResolve();
    });
  });
}

function afterEach() {
  return new Promise(function(afterEachResolve, afterEachReject) {

    async.series([

      function(socketStopDone) {
        if (socket) {
          socket.disconnect();
          socket = null;
        }
        msgqueue = null;
        socketStopDone();
      },

      function(stopContainerDone) {
        docker.stopContainer().then(function() {
          stopContainerDone();
        }).catch(function(err) {
          stopContainerDone(err);
        });
      }
    ],
    function(err) {
      if (err)
        afterEachReject(err);
      else
        afterEachResolve();
    });
  });
}

function hears(msg, channelId) {
  if (!channelId) channelId = channelIdDefault;

  return new Promise(function(hearsResolve, hearsReject) {
    if (socket) {
      socket.emit('bothears', channelId, msg);
      hearsResolve();
    } else {
      hearsReject('Socket not online');
    }
  });
}

function says(channelId, timeoutMillis) {
  if (!channelId) channelId = channelIdDefault;

  return new Promise(function(saysResolve, saysReject) {

    if (!timeoutMillis)
      timeoutMillis = config.defaultsaytimeout;

    var timeoutRequest = async.timeout(function(callback) {
      msgqueue.registerListener(
        (msg) => {
          callback(null, msg);
        },
        channelId);
    }, timeoutMillis);

    timeoutRequest(function(err, body) {
      if (err && err.code === 'ETIMEDOUT') {
        saysReject('nothing said in time');
      } else if (err) {
        saysReject('says error: ' + err);
      } else {
        saysResolve(body);
      }
    });
  });
}

function setupTestSuite(testcaseCb, assertCb, failCb) {

  var testcaseFiles = convo.getConvoFilesSync();

  testcaseFiles.forEach(function(testcaseFile) {
    log.info('adding test case file ' + testcaseFile);

    testcaseCb(testcaseFile, function(testcaseDone) {
      log.info('running testcase ' + testcaseFile);

      convo.readConvo(testcaseFile).then(
        (testcase) => {

          async.eachSeries(testcase.conversation,
            (convomsg, convomsgDone) => {

              if (convomsg.from === 'me') {
                log.debug(testcase.name + ': hears ' + convomsg.msg);
                hears(convomsg.msg).then(convomsgDone).catch(convomsgDone);
              } else if (convomsg.from === 'bot') {
                log.debug(testcase.name + ': wait for says ');
                says().then((saysmsg) => {
                  if (saysmsg.messageText) {
                    log.debug(testcase.name + ': says ' + saysmsg.messageText);
                    assertCb(saysmsg.messageText, convomsg.msg);
                  } else {
                    log.debug(testcase.name + ': says ' + JSON.stringify(saysmsg));
                    compareObject(assertCb, failCb, saysmsg, convomsg.msg);
                  }
                  convomsgDone();
                }).catch((err) => {
                  convomsgDone(err);
                });
              }
            },
            (err) => {
              if (err) {
                log.info(testcase.name + ' failed: ' + err);
                failCb(err);
              }
              log.info(testcase.name + ' ready, calling done function.');
              testcaseDone();
            });

        },
        (err) => {
          failCb(err);
        });
    });
  });
}

function compareObject(assertCb, failCb, result, expected) {

  if (expected === null || expected === undefined)
    return;

  if (_.isObject(expected)) {
    _.forOwn(expected, function(value, key) {

      if (result.hasOwnProperty(key)) {
        compareObject(assertCb, failCb, result[key], expected[key]);
      } else {
        failCb('missing property: ' + key);
      }
    });
  } else {
    assertCb(result, expected);
  }
}

module.exports = {
  beforeAll: beforeAll,
  afterAll: afterAll,
  beforeEach : beforeEach,
  afterEach: afterEach,
  setupTestSuite: setupTestSuite,
  hears: hears,
  says: says,

};<|endoftext|>


<commit_before>module.exports=tokenize;

function tokenize(){}<commit_msg>created structure and travis.yml<commit_after>module.exports=tokenize;

function tokenize(){

}<|endoftext|>