<commit_before>var jsonUrl = "demotalks.json";
//var jsonUrl = "../rest/talks";
//var jsonUrl = "http://dev.dukecon.org/latest/rest/talks";
var originHeader = "http://dev.dukecon.org";

function Talk(data, isFavourite) {
    this.id = data.id || '';
    this.day = dukeconDateUtils.getDisplayDate(data.start);
    this.startDisplayed = dukeconDateUtils.getDisplayTime(data.start);
    this.startSortable = data.start || '';
    this.track = data.track || '';
    this.location = data.location || '';
    this.level = data.level || '';
    this.title = data.title || '';
    this.speakers = dukeconUtils.getSpeakerNames(data.speakers);
    this.speakerString = data.speakers ? data.speakers[0].name : ""; // TODO: comma-list
    this.language = data.language || '';
    this.fullAbstract = data.abstractText || '';
    this.shortAbstract = this.fullAbstract.substring(0, 100) + "...";
    this.favourite = ko.observable(isFavourite);
    this.favicon = ko.computed(function() {
        return this.favourite() ? "img/StarFilled.png" : "img/StarLine.png";
    }, this);
    this.toggleFavourite = function() {
        this.favourite(!this.favourite());
    };
    this.talkIcon = dukeconUtils.talkIcons[this.track];
};

function Speaker(name, company, talks) {
    this.name = name;
    this.company = company;
    this.talks = talks;
};

var dukeconDateUtils = {

    weekDays : ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],

    getDisplayDate : function(datetimeString) {
        if (!datetimeString) {
            return '';
        }
        var date = new Date(datetimeString);
        var month = this.addTrailingZero(date.getMonth() + 1);
        var day = this.addTrailingZero(date.getDate());
        var weekDay = this.weekDays[date.getDay()];
        return weekDay + ", " + day + "." + month;
    },

    getDisplayTime : function(datetimeString) {
        if (!datetimeString) {
            return '';
        }
        var date = new Date(datetimeString);
        return this.addTrailingZero(date.getHours()) + ":" + this.addTrailingZero(date.getMinutes());
    },

    addTrailingZero : function(data) {
        if (data < 10) {
            return '0' + data;
        }
        return data;
    }
};

//widgets
ko.components.register('header-widget', {
    viewModel : function(params) {
        this.title = params.value;
    },
    template:
        '
'
        + ''
        + '
'
        + 'Talks|Sprecher|Impressum'
        + '
'
        + '

'
        + '
'
});

ko.components.register('talk-widget', {
    viewModel: function(data) {
        this.talk = data.value;
    },
    template:
        '
'
            + '
'
                + ''
                + ''
            + '
'
            + '

'
            + '
 Start:

,
'
            + '
 Raum:
'
            + '
 Track:
'
            + '
'
});

//not sure where else to put
var dukeconUtils = {
    talkIcons : {
        "Architecture & Security": "img/track_architecture.jpg",
        "Core Java/JVM-basierte Sprachen": "img/track_jvm-languages.jpg",
        "Enterprise Java und Cloud": "img/track_enterprise-java-cloud.jpg",
        "Frontend & Mobile": "img/track_frontend-mobile.jpg",
        "IDEs & Tools": "img/track_ide-tools.jpg",
        "Container und Microservices": "img/track_microservices.jpg",
        "Internet der Dinge": "img/track_internet-of-things.jpg",
        "Newcomer": "img/track_newcomer.jpg"
    },

    getSpeakerNames : function(speakers) {
        var filteredSpeakers = _.filter(speakers, function(speaker) {
            return speaker;
        });
        return _.map(filteredSpeakers, function(speaker) {
            return speaker.name + ", " + speaker.company;
        });
    }
};
<commit_msg>Fix impressum link<commit_after>var jsonUrl = "demotalks.json";
//var jsonUrl = "../rest/talks";
//var jsonUrl = "http://dev.dukecon.org/latest/rest/talks";
var originHeader = "http://dev.dukecon.org";

function Talk(data, isFavourite) {
    this.id = data.id || '';
    this.day = dukeconDateUtils.getDisplayDate(data.start);
    this.startDisplayed = dukeconDateUtils.getDisplayTime(data.start);
    this.startSortable = data.start || '';
    this.track = data.track || '';
    this.location = data.location || '';
    this.level = data.level || '';
    this.title = data.title || '';
    this.speakers = dukeconUtils.getSpeakerNames(data.speakers);
    this.speakerString = data.speakers ? data.speakers[0].name : ""; // TODO: comma-list
    this.language = data.language || '';
    this.fullAbstract = data.abstractText || '';
    this.shortAbstract = this.fullAbstract.substring(0, 100) + "...";
    this.favourite = ko.observable(isFavourite);
    this.favicon = ko.computed(function() {
        return this.favourite() ? "img/StarFilled.png" : "img/StarLine.png";
    }, this);
    this.toggleFavourite = function() {
        this.favourite(!this.favourite());
    };
    this.talkIcon = dukeconUtils.talkIcons[this.track];
};

function Speaker(name, company, talks) {
    this.name = name;
    this.company = company;
    this.talks = talks;
};

var dukeconDateUtils = {

    weekDays : ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"],

    getDisplayDate : function(datetimeString) {
        if (!datetimeString) {
            return '';
        }
        var date = new Date(datetimeString);
        var month = this.addTrailingZero(date.getMonth() + 1);
        var day = this.addTrailingZero(date.getDate());
        var weekDay = this.weekDays[date.getDay()];
        return weekDay + ", " + day + "." + month;
    },

    getDisplayTime : function(datetimeString) {
        if (!datetimeString) {
            return '';
        }
        var date = new Date(datetimeString);
        return this.addTrailingZero(date.getHours()) + ":" + this.addTrailingZero(date.getMinutes());
    },

    addTrailingZero : function(data) {
        if (data < 10) {
            return '0' + data;
        }
        return data;
    }
};

//widgets
ko.components.register('header-widget', {
    viewModel : function(params) {
        this.title = params.value;
    },
    template:
        '
'
        + ''
        + '
'
        + 'Talks|Sprecher|Impressum'
        + '
'
        + '

'
        + '
'
});

ko.components.register('talk-widget', {
    viewModel: function(data) {
        this.talk = data.value;
    },
    template:
        '
'
            + '
'
                + ''
                + ''
            + '
'
            + '

'
            + '
 Start:

,
'
            + '
 Raum:
'
            + '
 Track:
'
            + '
'
});

//not sure where else to put
var dukeconUtils = {
    talkIcons : {
        "Architecture & Security": "img/track_architecture.jpg",
        "Core Java/JVM-basierte Sprachen": "img/track_jvm-languages.jpg",
        "Enterprise Java und Cloud": "img/track_enterprise-java-cloud.jpg",
        "Frontend & Mobile": "img/track_frontend-mobile.jpg",
        "IDEs & Tools": "img/track_ide-tools.jpg",
        "Container und Microservices": "img/track_microservices.jpg",
        "Internet der Dinge": "img/track_internet-of-things.jpg",
        "Newcomer": "img/track_newcomer.jpg"
    },

    getSpeakerNames : function(speakers) {
        var filteredSpeakers = _.filter(speakers, function(speaker) {
            return speaker;
        });
        return _.map(filteredSpeakers, function(speaker) {
            return speaker.name + ", " + speaker.company;
        });
    }
};
<|endoftext|>


<commit_before>/* global psl */
/* global url */
/* global util */

const OPTION_MODE = "mode";

const OPTION_MODE_OFF = "off";
const OPTION_MODE_NO_SKIP_URLS_LIST = "blacklist";
const OPTION_MODE_SKIP_URLS_LIST = "whitelist";

const OPTION_NO_SKIP_PARAMETERS_LIST = "no-skip-parameters-list";
const OPTION_NO_SKIP_URLS_LIST = "blacklist";
const OPTION_SKIP_URLS_LIST = "whitelist";
const OPTION_SYNC_LISTS_ENABLED = "syncListsEnabled";

const OPTION_NOTIFICATION_POPUP_ENABLED = "notificationPopupEnabled";
const OPTION_NOTIFICATION_DURATION = "notificationDuration";

const OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN = "skipRedirectsToSameDomain";

const LIST_OPTIONS = [
    OPTION_NO_SKIP_PARAMETERS_LIST,
    OPTION_NO_SKIP_URLS_LIST,
    OPTION_SKIP_URLS_LIST,
];

const CONTEXT_MENU_ID = "copy-last-source-url";
const NOTIFICATION_ID = "notify-skip";

const ICON = "icon.svg";
const ICON_OFF = "icon-off.svg";
const ICON_NO_SKIP_URLS_LIST = "icon-no-skip-urls-list.svg";
const ICON_SKIP_URLS_LIST = "icon-skip-urls-list.svg";

const MAX_NOTIFICATION_URL_LENGTH = 100;

const DEFAULT_NO_SKIP_PARAMETERS_LIST = [
    "from",
    "ref",
    "ref_url",
    "referer",
    "referrer",
    "source",
];

const DEFAULT_NO_SKIP_URLS_LIST = [
    "/abp",
    "/account",
    "/adfs",
    "/auth",
    "/cookie",
    "/download",
    "/login",
    "/logoff",
    "/logon",
    "/logout",
    "/oauth",
    "/preferences",
    "/profile",
    "/register",
    "/saml",
    "/signin",
    "/signoff",
    "/signon",
    "/signout",
    "/signup",
    "/sso",
    "/subscribe",
    "/unauthenticated",
    "/verification",
];

let currentMode = undefined;

let noSkipParametersList = [];
let noSkipUrlsList = [];
let skipUrlsList = [];

let lastSourceURL = undefined;

let notificationPopupEnabled = undefined;
let notificationDuration = undefined;

let skipRedirectsToSameDomain = false;
let syncLists = false;

let notificationTimeout = undefined;

browser.storage.local.get([
    OPTION_MODE,
    OPTION_NOTIFICATION_DURATION,
    OPTION_NOTIFICATION_POPUP_ENABLED,
    OPTION_NO_SKIP_PARAMETERS_LIST,
    OPTION_NO_SKIP_URLS_LIST,
    OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN,
    OPTION_SKIP_URLS_LIST,
    OPTION_SYNC_LISTS_ENABLED,
])
    .then(
        (result) => {

            if (result[OPTION_NO_SKIP_PARAMETERS_LIST] === undefined) {
                browser.storage.local.set({[OPTION_NO_SKIP_PARAMETERS_LIST]: DEFAULT_NO_SKIP_PARAMETERS_LIST});
            } else {
                updateNoSkipParametersList(result[OPTION_NO_SKIP_PARAMETERS_LIST]);
            }

            if (result[OPTION_NO_SKIP_URLS_LIST] === undefined) {
                browser.storage.local.set({[OPTION_NO_SKIP_URLS_LIST]: DEFAULT_NO_SKIP_URLS_LIST});
            } else {
                updateNoSkipUrlsList(result[OPTION_NO_SKIP_URLS_LIST]);
            }

            if (result[OPTION_SKIP_URLS_LIST] === undefined) {
                browser.storage.local.set({[OPTION_SKIP_URLS_LIST]: []});
            } else {
                updateSkipUrlsList(result[OPTION_SKIP_URLS_LIST]);
            }

            if (result[OPTION_MODE] === undefined) {
                browser.storage.local.set({[OPTION_MODE]: OPTION_MODE_NO_SKIP_URLS_LIST});
                currentMode = OPTION_MODE_NO_SKIP_URLS_LIST;
            } else {
                currentMode = result[OPTION_MODE];
            }

            if (currentMode === OPTION_MODE_OFF) {
                disableSkipping();
            } else {
                enableSkipping();
            }

            if (result[OPTION_NOTIFICATION_POPUP_ENABLED] === undefined) {
                browser.storage.local.set({[OPTION_NOTIFICATION_POPUP_ENABLED]: true});
            } else {
                notificationPopupEnabled = result[OPTION_NOTIFICATION_POPUP_ENABLED];
            }

            if (result[OPTION_NOTIFICATION_DURATION] === undefined) {
                browser.storage.local.set({[OPTION_NOTIFICATION_DURATION]: 3});
            } else {
                notificationDuration = result[OPTION_NOTIFICATION_DURATION];
            }

            if (result[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN] === undefined) {
                browser.storage.local.set({[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN]: false});
            } else {
                skipRedirectsToSameDomain = result[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN];
            }

        }
    );

browser.storage.onChanged.addListener(
    (changes, areaName) => {

        let initTriggered = false;
        if (changes[OPTION_SYNC_LISTS_ENABLED]) {
            const previousValue = syncLists;
            const newValue = changes[OPTION_SYNC_LISTS_ENABLED].newValue;
            syncLists = newValue;
            if (previousValue !== newValue && syncLists) {
                initTriggered = true;
                initSyncLists();
            }
        }

        if (changes[OPTION_NO_SKIP_PARAMETERS_LIST]) {
            updateNoSkipParametersList(changes[OPTION_NO_SKIP_PARAMETERS_LIST].newValue);
            if (!initTriggered){
                maybeSyncList(areaName, OPTION_NO_SKIP_PARAMETERS_LIST, noSkipParametersList);
            }
        }

        if (changes[OPTION_NO_SKIP_URLS_LIST]) {
            updateNoSkipUrlsList(changes[OPTION_NO_SKIP_URLS_LIST].newValue);
            if (!initTriggered){
                maybeSyncList(areaName, OPTION_NO_SKIP_URLS_LIST, noSkipUrlsList);
            }
        }

        if (changes[OPTION_SKIP_URLS_LIST]) {
            updateSkipUrlsList(changes[OPTION_SKIP_URLS_LIST].newValue);
            if (!initTriggered){
                maybeSyncList(areaName, OPTION_SKIP_URLS_LIST, skipUrlsList);
            }
        }

        if (changes[OPTION_MODE]) {
            currentMode = changes[OPTION_MODE].newValue;
        }

        if (currentMode === OPTION_MODE_OFF) {
            disableSkipping();
        } else {
            enableSkipping();
        }

        if (changes[OPTION_NOTIFICATION_POPUP_ENABLED]) {
            notificationPopupEnabled = changes[OPTION_NOTIFICATION_POPUP_ENABLED].newValue;
        }

        if (changes[OPTION_NOTIFICATION_DURATION]) {
            notificationDuration = changes[OPTION_NOTIFICATION_DURATION].newValue;
        }

        if (changes[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN]) {
            skipRedirectsToSameDomain = changes[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN].newValue;
        }

    }
);

browser.contextMenus.create({
    id: CONTEXT_MENU_ID,
    title: browser.i18n.getMessage("contextMenuLabel"),
    contexts: ["browser_action"],
    enabled: false,
});

browser.contextMenus.onClicked.addListener(
    (info, _tab) => {
        if (info.menuItemId === CONTEXT_MENU_ID) {
            copyLastSourceURLToClipboard();
        }
    }
);

function copyLastSourceURLToClipboard() {
    chainPromises([
        ()        => { return browser.tabs.executeScript({ code: "typeof copyToClipboard === 'function';" }); },
        (results) => { return injectScriptIfNecessary(results && results[0]); },
        ()        => { return browser.tabs.executeScript({ code: `copyToClipboard("${lastSourceURL}")` }); },
    ]);
}

function injectScriptIfNecessary(isCopyFunctionDefined) {
    if (!isCopyFunctionDefined) {
        return browser.tabs.executeScript({ file: "clipboard-helper.js" });
    }
}

function updateNoSkipParametersList(newNoSkipParametersList) {
    noSkipParametersList = newNoSkipParametersList.filter(Boolean);
}

function updateNoSkipUrlsList(newNoSkipUrlsList) {
    noSkipUrlsList = newNoSkipUrlsList.filter(Boolean);
}

function updateSkipUrlsList(newSkipUrlsList) {
    skipUrlsList = newSkipUrlsList.filter(Boolean);
}

function initSyncLists() {
    Promise.all([
        browser.storage.local.get(LIST_OPTIONS),
        browser.storage.sync.get(LIST_OPTIONS),
    ])
        .then(
            ([localResult, remoteResult]) => {
                LIST_OPTIONS.forEach((optionName) => {
                    const localValue = localResult[optionName];
                    const remoteValue = remoteResult[optionName];
                    const newValue = util.mergeList(localValue, remoteValue);
                    browser.storage.local.set({[optionName]: newValue});
                });
            }
        );
}

function maybeSyncList(changedArea, optionName, optionValue) {
    if (!syncLists) {
        return;
    }

    const toAreaName = changedArea === "local" ? "sync" : "local";
    const toArea = browser.storage[toAreaName];

    toArea.get([optionName]).then(
        (result) => {
            const targetValue = result[optionName];
            if (JSON.stringify(targetValue) !== JSON.stringify(optionValue)){
                toArea.set({[optionName]: optionValue});
            }
        }
    );
}

function enableSkipping() {
    browser.webRequest.onBeforeRequest.removeListener(maybeRedirect);

    if (currentMode === OPTION_MODE_NO_SKIP_URLS_LIST) {
        browser.webRequest.onBeforeRequest.addListener(
            maybeRedirect,
            {urls: ["<all_urls>"], types: ["main_frame"]},
            ["blocking"]
        );
        browser.browserAction.setIcon({path: ICON_NO_SKIP_URLS_LIST});
    } else if (currentMode === OPTION_MODE_SKIP_URLS_LIST) {
        if (skipUrlsList.length > 0) {
            browser.webRequest.onBeforeRequest.addListener(
                maybeRedirect,
                {urls: skipUrlsList, types: ["main_frame"]},
                ["blocking"]
            );
        }

        browser.browserAction.setIcon({path: ICON_SKIP_URLS_LIST});
    }

    browser.browserAction.setBadgeBackgroundColor({color: "red"});
    browser.browserAction.setTitle({title: browser.i18n.getMessage("browserActionLabelOn")});
}

function disableSkipping() {
    browser.webRequest.onBeforeRequest.removeListener(maybeRedirect);

    browser.browserAction.setIcon({path: ICON_OFF});
    browser.browserAction.setTitle({title: browser.i18n.getMessage("browserActionLabelOff")});
}

function maybeRedirect(requestDetails) {
    if (requestDetails.tabId === -1 || requestDetails.method === "POST") {
        return;
    }

    const parameterExceptions = noSkipParametersList;
    let urlExceptions = [];
    if (currentMode === OPTION_MODE_NO_SKIP_URLS_LIST) {
        urlExceptions = noSkipUrlsList;
    }

    const redirectTarget = url.getRedirectTarget(requestDetails.url, urlExceptions, parameterExceptions);
    if (redirectTarget === requestDetails.url) {
        return;
    }

    if (currentMode === OPTION_MODE_NO_SKIP_URLS_LIST && !skipRedirectsToSameDomain) {
        const sourceHostname = getHostname(requestDetails.url);
        const targetHostname = getHostname(redirectTarget);
        const sourceDomain = psl.getDomain(sourceHostname);
        const targetDomain = psl.getDomain(targetHostname);
        if (sourceDomain === targetDomain) {
            return;
        }
    }

    prepareContextMenu(requestDetails.url);
    notifySkip(requestDetails.url, redirectTarget);

    return {
        redirectUrl: redirectTarget,
    };
}

function prepareContextMenu(from) {
    if (lastSourceURL === undefined) {
        browser.contextMenus.update(CONTEXT_MENU_ID, {enabled: true});
    }
    lastSourceURL = from;
}

function notifySkip(from, to) {
    if (notificationTimeout) {
        clearNotifications();
    }

    const notificationMessage = browser.i18n.getMessage("redirectSkippedNotificationMessage", [cleanUrl(from), cleanUrl(to)]);

    const toolbarButtonTitle = browser.i18n.getMessage("browserActionLabelOnSkipped", [from, to]);

    if (notificationPopupEnabled) {
        browser.notifications.create(NOTIFICATION_ID, {
            type: "basic",
            iconUrl: browser.extension.getURL(ICON),
            title: browser.i18n.getMessage("redirectSkippedNotificationTitle"),
            message: notificationMessage,
        });
    }
    browser.browserAction.setBadgeText({text: browser.i18n.getMessage("redirectSkippedBrowserActionBadge")});

    browser.browserAction.setTitle({title: toolbarButtonTitle});

    notificationTimeout = setTimeout(clearNotifications, 1000 * notificationDuration);
}

function clearNotifications() {
    clearTimeout(notificationTimeout);
    notificationTimeout = undefined;
    browser.notifications.clear(NOTIFICATION_ID);
    browser.browserAction.setBadgeText({text: ""});
}

function cleanUrl(string) {
    if (string.length > MAX_NOTIFICATION_URL_LENGTH) {
        string = string.substring(0, MAX_NOTIFICATION_URL_LENGTH - 3) + "...";
    }

    return string.replace(/&/g, "&");
}

function getHostname(url) {
    const a = document.createElement("a");
    a.href = url;
    return a.hostname;
}

function chainPromises(functions) {
    let promise = Promise.resolve();
    for (const function_ of functions) {
        promise = promise.then(function_);
    }

    return promise.catch((error) => { console.warn(error.message); });
}
<commit_msg> Add missing syncList initialisation<commit_after>/* global psl */
/* global url */
/* global util */

const OPTION_MODE = "mode";

const OPTION_MODE_OFF = "off";
const OPTION_MODE_NO_SKIP_URLS_LIST = "blacklist";
const OPTION_MODE_SKIP_URLS_LIST = "whitelist";

const OPTION_NO_SKIP_PARAMETERS_LIST = "no-skip-parameters-list";
const OPTION_NO_SKIP_URLS_LIST = "blacklist";
const OPTION_SKIP_URLS_LIST = "whitelist";
const OPTION_SYNC_LISTS_ENABLED = "syncListsEnabled";

const OPTION_NOTIFICATION_POPUP_ENABLED = "notificationPopupEnabled";
const OPTION_NOTIFICATION_DURATION = "notificationDuration";

const OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN = "skipRedirectsToSameDomain";

const LIST_OPTIONS = [
    OPTION_NO_SKIP_PARAMETERS_LIST,
    OPTION_NO_SKIP_URLS_LIST,
    OPTION_SKIP_URLS_LIST,
];

const CONTEXT_MENU_ID = "copy-last-source-url";
const NOTIFICATION_ID = "notify-skip";

const ICON = "icon.svg";
const ICON_OFF = "icon-off.svg";
const ICON_NO_SKIP_URLS_LIST = "icon-no-skip-urls-list.svg";
const ICON_SKIP_URLS_LIST = "icon-skip-urls-list.svg";

const MAX_NOTIFICATION_URL_LENGTH = 100;

const DEFAULT_NO_SKIP_PARAMETERS_LIST = [
    "from",
    "ref",
    "ref_url",
    "referer",
    "referrer",
    "source",
];

const DEFAULT_NO_SKIP_URLS_LIST = [
    "/abp",
    "/account",
    "/adfs",
    "/auth",
    "/cookie",
    "/download",
    "/login",
    "/logoff",
    "/logon",
    "/logout",
    "/oauth",
    "/preferences",
    "/profile",
    "/register",
    "/saml",
    "/signin",
    "/signoff",
    "/signon",
    "/signout",
    "/signup",
    "/sso",
    "/subscribe",
    "/unauthenticated",
    "/verification",
];

let currentMode = undefined;

let noSkipParametersList = [];
let noSkipUrlsList = [];
let skipUrlsList = [];

let lastSourceURL = undefined;

let notificationPopupEnabled = undefined;
let notificationDuration = undefined;

let skipRedirectsToSameDomain = false;
let syncLists = false;

let notificationTimeout = undefined;

browser.storage.local.get([
    OPTION_MODE,
    OPTION_NOTIFICATION_DURATION,
    OPTION_NOTIFICATION_POPUP_ENABLED,
    OPTION_NO_SKIP_PARAMETERS_LIST,
    OPTION_NO_SKIP_URLS_LIST,
    OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN,
    OPTION_SKIP_URLS_LIST,
    OPTION_SYNC_LISTS_ENABLED,
])
    .then(
        (result) => {

            if (result[OPTION_NO_SKIP_PARAMETERS_LIST] === undefined) {
                browser.storage.local.set({[OPTION_NO_SKIP_PARAMETERS_LIST]: DEFAULT_NO_SKIP_PARAMETERS_LIST});
            } else {
                updateNoSkipParametersList(result[OPTION_NO_SKIP_PARAMETERS_LIST]);
            }

            if (result[OPTION_NO_SKIP_URLS_LIST] === undefined) {
                browser.storage.local.set({[OPTION_NO_SKIP_URLS_LIST]: DEFAULT_NO_SKIP_URLS_LIST});
            } else {
                updateNoSkipUrlsList(result[OPTION_NO_SKIP_URLS_LIST]);
            }

            if (result[OPTION_SKIP_URLS_LIST] === undefined) {
                browser.storage.local.set({[OPTION_SKIP_URLS_LIST]: []});
            } else {
                updateSkipUrlsList(result[OPTION_SKIP_URLS_LIST]);
            }

            if (result[OPTION_MODE] === undefined) {
                browser.storage.local.set({[OPTION_MODE]: OPTION_MODE_NO_SKIP_URLS_LIST});
                currentMode = OPTION_MODE_NO_SKIP_URLS_LIST;
            } else {
                currentMode = result[OPTION_MODE];
            }

            if (currentMode === OPTION_MODE_OFF) {
                disableSkipping();
            } else {
                enableSkipping();
            }

            if (result[OPTION_NOTIFICATION_POPUP_ENABLED] === undefined) {
                browser.storage.local.set({[OPTION_NOTIFICATION_POPUP_ENABLED]: true});
            } else {
                notificationPopupEnabled = result[OPTION_NOTIFICATION_POPUP_ENABLED];
            }

            if (result[OPTION_NOTIFICATION_DURATION] === undefined) {
                browser.storage.local.set({[OPTION_NOTIFICATION_DURATION]: 3});
            } else {
                notificationDuration = result[OPTION_NOTIFICATION_DURATION];
            }

            if (result[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN] === undefined) {
                browser.storage.local.set({[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN]: false});
            } else {
                skipRedirectsToSameDomain = result[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN];
            }

            if (result[OPTION_SYNC_LISTS_ENABLED] === undefined) {
                browser.storage.local.set({[OPTION_SYNC_LISTS_ENABLED]: false});
            } else {
                syncLists = result[OPTION_SYNC_LISTS_ENABLED];
            }

        }
    );

browser.storage.onChanged.addListener(
    (changes, areaName) => {

        let initTriggered = false;
        if (changes[OPTION_SYNC_LISTS_ENABLED]) {
            const previousValue = syncLists;
            const newValue = changes[OPTION_SYNC_LISTS_ENABLED].newValue;
            syncLists = newValue;
            if (previousValue !== newValue && syncLists) {
                initTriggered = true;
                initSyncLists();
            }
        }

        if (changes[OPTION_NO_SKIP_PARAMETERS_LIST]) {
            updateNoSkipParametersList(changes[OPTION_NO_SKIP_PARAMETERS_LIST].newValue);
            if (!initTriggered){
                maybeSyncList(areaName, OPTION_NO_SKIP_PARAMETERS_LIST, noSkipParametersList);
            }
        }

        if (changes[OPTION_NO_SKIP_URLS_LIST]) {
            updateNoSkipUrlsList(changes[OPTION_NO_SKIP_URLS_LIST].newValue);
            if (!initTriggered){
                maybeSyncList(areaName, OPTION_NO_SKIP_URLS_LIST, noSkipUrlsList);
            }
        }

        if (changes[OPTION_SKIP_URLS_LIST]) {
            updateSkipUrlsList(changes[OPTION_SKIP_URLS_LIST].newValue);
            if (!initTriggered){
                maybeSyncList(areaName, OPTION_SKIP_URLS_LIST, skipUrlsList);
            }
        }

        if (changes[OPTION_MODE]) {
            currentMode = changes[OPTION_MODE].newValue;
        }

        if (currentMode === OPTION_MODE_OFF) {
            disableSkipping();
        } else {
            enableSkipping();
        }

        if (changes[OPTION_NOTIFICATION_POPUP_ENABLED]) {
            notificationPopupEnabled = changes[OPTION_NOTIFICATION_POPUP_ENABLED].newValue;
        }

        if (changes[OPTION_NOTIFICATION_DURATION]) {
            notificationDuration = changes[OPTION_NOTIFICATION_DURATION].newValue;
        }

        if (changes[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN]) {
            skipRedirectsToSameDomain = changes[OPTION_SKIP_REDIRECTS_TO_SAME_DOMAIN].newValue;
        }

    }
);

browser.contextMenus.create({
    id: CONTEXT_MENU_ID,
    title: browser.i18n.getMessage("contextMenuLabel"),
    contexts: ["browser_action"],
    enabled: false,
});

browser.contextMenus.onClicked.addListener(
    (info, _tab) => {
        if (info.menuItemId === CONTEXT_MENU_ID) {
            copyLastSourceURLToClipboard();
        }
    }
);

function copyLastSourceURLToClipboard() {
    chainPromises([
        ()        => { return browser.tabs.executeScript({ code: "typeof copyToClipboard === 'function';" }); },
        (results) => { return injectScriptIfNecessary(results && results[0]); },
        ()        => { return browser.tabs.executeScript({ code: `copyToClipboard("${lastSourceURL}")` }); },
    ]);
}

function injectScriptIfNecessary(isCopyFunctionDefined) {
    if (!isCopyFunctionDefined) {
        return browser.tabs.executeScript({ file: "clipboard-helper.js" });
    }
}

function updateNoSkipParametersList(newNoSkipParametersList) {
    noSkipParametersList = newNoSkipParametersList.filter(Boolean);
}

function updateNoSkipUrlsList(newNoSkipUrlsList) {
    noSkipUrlsList = newNoSkipUrlsList.filter(Boolean);
}

function updateSkipUrlsList(newSkipUrlsList) {
    skipUrlsList = newSkipUrlsList.filter(Boolean);
}

function initSyncLists() {
    Promise.all([
        browser.storage.local.get(LIST_OPTIONS),
        browser.storage.sync.get(LIST_OPTIONS),
    ])
        .then(
            ([localResult, remoteResult]) => {
                LIST_OPTIONS.forEach((optionName) => {
                    const localValue = localResult[optionName];
                    const remoteValue = remoteResult[optionName];
                    const newValue = util.mergeList(localValue, remoteValue);
                    browser.storage.local.set({[optionName]: newValue});
                });
            }
        );
}

function maybeSyncList(changedArea, optionName, optionValue) {
    if (!syncLists) {
        return;
    }

    const toAreaName = changedArea === "local" ? "sync" : "local";
    const toArea = browser.storage[toAreaName];

    toArea.get([optionName]).then(
        (result) => {
            const targetValue = result[optionName];
            if (JSON.stringify(targetValue) !== JSON.stringify(optionValue)){
                toArea.set({[optionName]: optionValue});
            }
        }
    );
}

function enableSkipping() {
    browser.webRequest.onBeforeRequest.removeListener(maybeRedirect);

    if (currentMode === OPTION_MODE_NO_SKIP_URLS_LIST) {
        browser.webRequest.onBeforeRequest.addListener(
            maybeRedirect,
            {urls: ["<all_urls>"], types: ["main_frame"]},
            ["blocking"]
        );
        browser.browserAction.setIcon({path: ICON_NO_SKIP_URLS_LIST});
    } else if (currentMode === OPTION_MODE_SKIP_URLS_LIST) {
        if (skipUrlsList.length > 0) {
            browser.webRequest.onBeforeRequest.addListener(
                maybeRedirect,
                {urls: skipUrlsList, types: ["main_frame"]},
                ["blocking"]
            );
        }

        browser.browserAction.setIcon({path: ICON_SKIP_URLS_LIST});
    }

    browser.browserAction.setBadgeBackgroundColor({color: "red"});
    browser.browserAction.setTitle({title: browser.i18n.getMessage("browserActionLabelOn")});
}

function disableSkipping() {
    browser.webRequest.onBeforeRequest.removeListener(maybeRedirect);

    browser.browserAction.setIcon({path: ICON_OFF});
    browser.browserAction.setTitle({title: browser.i18n.getMessage("browserActionLabelOff")});
}

function maybeRedirect(requestDetails) {
    if (requestDetails.tabId === -1 || requestDetails.method === "POST") {
        return;
    }

    const parameterExceptions = noSkipParametersList;
    let urlExceptions = [];
    if (currentMode === OPTION_MODE_NO_SKIP_URLS_LIST) {
        urlExceptions = noSkipUrlsList;
    }

    const redirectTarget = url.getRedirectTarget(requestDetails.url, urlExceptions, parameterExceptions);
    if (redirectTarget === requestDetails.url) {
        return;
    }

    if (currentMode === OPTION_MODE_NO_SKIP_URLS_LIST && !skipRedirectsToSameDomain) {
        const sourceHostname = getHostname(requestDetails.url);
        const targetHostname = getHostname(redirectTarget);
        const sourceDomain = psl.getDomain(sourceHostname);
        const targetDomain = psl.getDomain(targetHostname);
        if (sourceDomain === targetDomain) {
            return;
        }
    }

    prepareContextMenu(requestDetails.url);
    notifySkip(requestDetails.url, redirectTarget);

    return {
        redirectUrl: redirectTarget,
    };
}

function prepareContextMenu(from) {
    if (lastSourceURL === undefined) {
        browser.contextMenus.update(CONTEXT_MENU_ID, {enabled: true});
    }
    lastSourceURL = from;
}

function notifySkip(from, to) {
    if (notificationTimeout) {
        clearNotifications();
    }

    const notificationMessage = browser.i18n.getMessage("redirectSkippedNotificationMessage", [cleanUrl(from), cleanUrl(to)]);

    const toolbarButtonTitle = browser.i18n.getMessage("browserActionLabelOnSkipped", [from, to]);

    if (notificationPopupEnabled) {
        browser.notifications.create(NOTIFICATION_ID, {
            type: "basic",
            iconUrl: browser.extension.getURL(ICON),
            title: browser.i18n.getMessage("redirectSkippedNotificationTitle"),
            message: notificationMessage,
        });
    }
    browser.browserAction.setBadgeText({text: browser.i18n.getMessage("redirectSkippedBrowserActionBadge")});

    browser.browserAction.setTitle({title: toolbarButtonTitle});

    notificationTimeout = setTimeout(clearNotifications, 1000 * notificationDuration);
}

function clearNotifications() {
    clearTimeout(notificationTimeout);
    notificationTimeout = undefined;
    browser.notifications.clear(NOTIFICATION_ID);
    browser.browserAction.setBadgeText({text: ""});
}

function cleanUrl(string) {
    if (string.length > MAX_NOTIFICATION_URL_LENGTH) {
        string = string.substring(0, MAX_NOTIFICATION_URL_LENGTH - 3) + "...";
    }

    return string.replace(/&/g, "&");
}

function getHostname(url) {
    const a = document.createElement("a");
    a.href = url;
    return a.hostname;
}

function chainPromises(functions) {
    let promise = Promise.resolve();
    for (const function_ of functions) {
        promise = promise.then(function_);
    }

    return promise.catch((error) => { console.warn(error.message); });
}
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
require('dotenv').load();
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
require(path.join(__dirname, 'app_server/controllers', 'socketConfig.js'));

var routes = require('./app_server/routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'app_server', 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'app_client')));

app.use('/email', routes);
// Send static html file, routing handled on client
app.use(function(req, res) {
  res.sendFile(path.join(__dirname, 'app_client', 'index.html'));
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<commit_msg>set port in .env<commit_after>var express = require('express');
var path = require('path');
require('dotenv').load();
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
require(path.join(__dirname, 'app_server/controllers', 'socketConfig.js'));

var routes = require('./app_server/routes/index');

var app = express();
var port = process.env.SERVER_PORT || 3000
app.listen(port, function() {
  console.log('Server listening on port ' + port);
});

// view engine setup
app.set('views', path.join(__dirname, 'app_server', 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'app_client')));

app.use('/email', routes);
// Send static html file, routing handled on client
app.use(function(req, res) {
  res.sendFile(path.join(__dirname, 'app_client', 'index.html'));
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<|endoftext|>


<commit_before>namespaces = {};
$(document).ready(function(){
	var query = "SELECT ?ns ?prefix WHERE { ?ns <http://data.mysema.com/schemas/meta#nsPrefix> ?prefix }";
	$.ajax({
		url: "query",
		data: { query: query},
		datatype: "json",
		beforeSend : function (xhr) {
    		xhr.setRequestHeader('Accept', 'application/sparql-results+json');
		},
		success: function(data){
			var queryTemplate = [];
			var bindings = data.results.bindings;
			for (var i = 0; i < bindings.length; i++){
				var binding = bindings[i];
				queryTemplate.push("PREFIX ", binding["prefix"].value, ": <", binding["ns"].value, ">\n");
			}

			queryTemplate.push("\nSELECT ?value \nWHERE { ?item rdf:value ?value }");

			$("#query").val(queryTemplate.join(""));
		}
	});

	$("#formsubmit").click(function(){
		var query = $("#query").val();
		$.ajax({
			url: "query",
			data: { query: query},
			datatype: "json",
			beforeSend : function (xhr) {
        		xhr.setRequestHeader('Accept', 'application/sparql-results+json');
    		},
			success: function(data){
				var vars = data.head.vars;
				var bindings = data.results.bindings;
				var html = new Array();
				html.push("
Results
");
				html.push("
");

				// head
				html.push("

");
				for (var i = 0; i < vars.length; i++){
				//for (var v in vars) {
					html.push("" + vars[i] + "	");
				}
				html.push("

");

				// body
				html.push("
");
				for (var i = 0; i < bindings.length; i++){
					var binding = bindings[i];
					html.push("
");
					for (var key in binding){
						html.push("" + binding[key].value + "	");
					}
					html.push("
");
				}
				html.push("
");

				html.push("
");
				$("#results").html(html.join(""));
			}
		});
		return false;
	});
});
			<commit_msg>Improved UI<commit_after>namespaces = {};

String.prototype.startsWith = function(str) {return (this.match("^"+str)==str)}

$(document).ready(function(){
	var query = "SELECT ?ns ?prefix WHERE { ?ns <http://data.mysema.com/schemas/meta#nsPrefix> ?prefix }";
	$.ajax({
		url: "query",
		data: { query: query},
		datatype: "json",
		beforeSend : function (xhr) {
    		xhr.setRequestHeader('Accept', 'application/sparql-results+json');
		},
		success: function(data){
			var queryTemplate = [];
			var bindings = data.results.bindings;
			for (var i = 0; i < bindings.length; i++){
				var binding = bindings[i];
				namespaces[binding["prefix"].value] = binding["ns"].value;
				queryTemplate.push("PREFIX ", binding["prefix"].value, ": <", binding["ns"].value, ">\n");
			}

			queryTemplate.push("\nSELECT ?value \nWHERE { \n?item rdf:value ?value . \n}");

			$("#query").val(queryTemplate.join(""));
		}
	});

	$("#formsubmit").click(function(){
		var query = $("#query").val();
		$.ajax({
			url: "query",
			data: { query: query},
			datatype: "json",
			beforeSend : function (xhr) {
        		xhr.setRequestHeader('Accept', 'application/sparql-results+json');
    		},
			success: function(data){
				var vars = data.head.vars;
				var bindings = data.results.bindings;
				var html = new Array();
				html.push("
Results
");
				html.push("
");

				// head
				html.push("

");
				for (var i = 0; i < vars.length; i++){
				//for (var v in vars) {
					html.push("" + vars[i] + "	");
				}
				html.push("

");

				// body
				html.push("
");
				var lastColumns = [];
				for (var i = 0; i < bindings.length; i++){
					var binding = bindings[i];
					html.push("
");
					for (var j = 0; j < vars.length; j++){
						var key = vars[j];
						if (lastColumns[j] != null && lastColumns[j] == binding[key].value) {
							binding[key].value = "";
						} else {
							lastColumns[j] = binding[key].value;
						}
						if ("uri" == binding[key].type) {
							html.push("" + printURI(binding[key].value) + "	");
						} else if ("literal" == binding[key].type) {
							html.push("" + binding[key].value.replace(/\n/g, "
") + "	");
 						} else {
							html.push("" + binding[key].value + "	");
						}
					}
					html.push("
");
				}
				html.push("
");

				html.push("
");
				$("#results").html(html.join(""));
			}
		});
		return false;
	});
});

function printURI(uri) {
	if (uri == "") {
		return "";
	} else {
		for (var key in namespaces){
			if (uri.startsWith(namespaces[key])) {
				return key + ":" + uri.substring(namespaces[key].length);
			}
		}
		return "<" + uri + ">";
	}
}<|endoftext|>


<commit_before>const USER_AGENT = 'Explode/0.8';
const API_ROOT = 'http://api.longurl.org/v2/';
const FETCH_DELAY = 800;
const SERVICES_CACHE_TIME = 86400 * 1000;
const DEFAULT_EXTRAS = [
    '3.ly',
    'disq.us',
    'dlvr.it',
    'flic.kr',
    'goo.gl',
    'guao.cc',
    'j.mp',
    'jan.io',
    'om.ly',
    'ouj.de',
    'ow.ly',
    'sn.im',
    't.co',
    'tcrn.ch',
    'urlz.at',
    'w33.us'
];

if (!localStorage['extraServices'])
    localStorage['extraServices'] = DEFAULT_EXTRAS.join(' ');

var outstandingReqs = [];
var curReq = null;

/* Functions for dealing with the LongURL API */

function xhrGet(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4)
            callback(xhr);
    };
    xhr.send();
}

function apiUrl(method, params) {
    var url = API_ROOT + method + '?format=json&user-agent=' +
        encodeURIComponent(USER_AGENT);
    for (k in params)
        url += '&' + k + '=' + encodeURIComponent(params[k]);
    return url;
}

/* Setup the service list; fetch and cache again if needed */

function loadCachedServices() {
    var services = JSON.parse(localStorage['services']);
    localStorage['extraServices'].split(' ').forEach(function(s) {
        services[s] = {host: s, regex: null};
    });
    return services;
}

chrome.extension.onRequest.addListener(function(req, sender, callback) {
    if (req.servicesPlease) {
        if (localStorage['servicesExpire'] > Date.now()) {
            callback({services: loadCachedServices()});
        } else {
            xhrGet(apiUrl('services'), function(xhr) {
                var date = Date.parse(xhr.getResponseHeader('Date'));
                localStorage['services'] = xhr.responseText;
                localStorage['servicesExpire'] = date + SERVICES_CACHE_TIME;
                callback({services: loadCachedServices()});
            });
        }
    }
});

/* Handle a bunch of requests from the content script. We stuff the
 * callback into req so we can pull it out later. All the requests
 * should finish coming in almost immediately, at which point the first
 * req's XHR will be running and the rest will be queued up. */

chrome.extension.onConnect.addListener(function (port) {
    switch (port.name) {
    case 'explodeUrlRequest':
        port.onMessage.addListener(function (req) {
            handleReq(req, port);
        });
    }
});

function handleReq(req, port) {
    if (localStorage[req.url]) {
        console.log('cached: ' + req.url);
        updateLink({url: req.url, port: port});
    } else {
        console.log('new: ' + req.url);
        port.postMessage({url: req.url, loading: true});
        outstandingReqs.push({url: req.url, port: port});
        fetchReqs();
    }
}

/* The main loop, so to speak. */

function fetchReqs() {
    if (curReq || outstandingReqs.length == 0)
        return;
    curReq = outstandingReqs.shift();
    if (localStorage[curReq.url]) {
        updateLink(curReq);
        fetchNextReq();
    } else {
        xhrGet(apiUrl('expand', {title: 1, url: curReq.url}), function(xhr) {
            var res = loadResponse(xhr.responseText);
            if (res) {
                localStorage[curReq.url] = JSON.stringify(res);
                updateLink(curReq);
            } else {
                curReq.port.postMessage({url: curReq.url, failed: true});
            }
            fetchNextReq();
        });
    }
}

function fetchNextReq() {
    curReq = null;
    setTimeout(fetchReqs, FETCH_DELAY);
}

function normalize(s) {
    var textarea = document.createElement('textarea');
    if (s) textarea.innerHTML = s.replace(/\s+/g, ' ');
    return textarea.value;
}

function loadResponse(t) {
    try {
        var res = JSON.parse(t);
        if (res['long-url']) {
            return { longUrl: res['long-url'], title: normalize(res.title) };
        } else {
            console.log('error: ' + t);
        }
    } catch (e) {
        console.log('no reply: ' + curReq.url);
    }
    return null;
}

/* And here's where we actually invoke the callback once the URL and
 * title come back from LongURL. */

function updateLink(req) {
    var info = JSON.parse(localStorage[req.url]);
    info.url = req.url;
    info.munge = localStorage['mungeLinks'] == 'true';
    req.port.postMessage(info);
}
<commit_msg>Decrease FETCH_DELAY<commit_after>const USER_AGENT = 'Explode/0.8';
const API_ROOT = 'http://api.longurl.org/v2/';
const FETCH_DELAY = 500;
const SERVICES_CACHE_TIME = 86400 * 1000;
const DEFAULT_EXTRAS = [
    '3.ly',
    'disq.us',
    'dlvr.it',
    'flic.kr',
    'goo.gl',
    'guao.cc',
    'j.mp',
    'jan.io',
    'om.ly',
    'ouj.de',
    'ow.ly',
    'sn.im',
    't.co',
    'tcrn.ch',
    'urlz.at',
    'w33.us'
];

if (!localStorage['extraServices'])
    localStorage['extraServices'] = DEFAULT_EXTRAS.join(' ');

var outstandingReqs = [];
var curReq = null;

/* Functions for dealing with the LongURL API */

function xhrGet(url, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4)
            callback(xhr);
    };
    xhr.send();
}

function apiUrl(method, params) {
    var url = API_ROOT + method + '?format=json&user-agent=' +
        encodeURIComponent(USER_AGENT);
    for (k in params)
        url += '&' + k + '=' + encodeURIComponent(params[k]);
    return url;
}

/* Setup the service list; fetch and cache again if needed */

function loadCachedServices() {
    var services = JSON.parse(localStorage['services']);
    localStorage['extraServices'].split(' ').forEach(function(s) {
        services[s] = {host: s, regex: null};
    });
    return services;
}

chrome.extension.onRequest.addListener(function(req, sender, callback) {
    if (req.servicesPlease) {
        if (localStorage['servicesExpire'] > Date.now()) {
            callback({services: loadCachedServices()});
        } else {
            xhrGet(apiUrl('services'), function(xhr) {
                var date = Date.parse(xhr.getResponseHeader('Date'));
                localStorage['services'] = xhr.responseText;
                localStorage['servicesExpire'] = date + SERVICES_CACHE_TIME;
                callback({services: loadCachedServices()});
            });
        }
    }
});

/* Handle a bunch of requests from the content script. We stuff the
 * callback into req so we can pull it out later. All the requests
 * should finish coming in almost immediately, at which point the first
 * req's XHR will be running and the rest will be queued up. */

chrome.extension.onConnect.addListener(function (port) {
    switch (port.name) {
    case 'explodeUrlRequest':
        port.onMessage.addListener(function (req) {
            handleReq(req, port);
        });
    }
});

function handleReq(req, port) {
    if (localStorage[req.url]) {
        console.log('cached: ' + req.url);
        updateLink({url: req.url, port: port});
    } else {
        console.log('new: ' + req.url);
        port.postMessage({url: req.url, loading: true});
        outstandingReqs.push({url: req.url, port: port});
        fetchReqs();
    }
}

/* The main loop, so to speak. */

function fetchReqs() {
    if (curReq || outstandingReqs.length == 0)
        return;
    curReq = outstandingReqs.shift();
    if (localStorage[curReq.url]) {
        updateLink(curReq);
        fetchNextReq();
    } else {
        xhrGet(apiUrl('expand', {title: 1, url: curReq.url}), function(xhr) {
            var res = loadResponse(xhr.responseText);
            if (res) {
                localStorage[curReq.url] = JSON.stringify(res);
                updateLink(curReq);
            } else {
                curReq.port.postMessage({url: curReq.url, failed: true});
            }
            fetchNextReq();
        });
    }
}

function fetchNextReq() {
    curReq = null;
    setTimeout(fetchReqs, FETCH_DELAY);
}

function normalize(s) {
    var textarea = document.createElement('textarea');
    if (s) textarea.innerHTML = s.replace(/\s+/g, ' ');
    return textarea.value;
}

function loadResponse(t) {
    try {
        var res = JSON.parse(t);
        if (res['long-url']) {
            return { longUrl: res['long-url'], title: normalize(res.title) };
        } else {
            console.log('error: ' + t);
        }
    } catch (e) {
        console.log('no reply: ' + curReq.url);
    }
    return null;
}

/* And here's where we actually invoke the callback once the URL and
 * title come back from LongURL. */

function updateLink(req) {
    var info = JSON.parse(localStorage[req.url]);
    info.url = req.url;
    info.munge = localStorage['mungeLinks'] == 'true';
    req.port.postMessage(info);
}
<|endoftext|>


<commit_before>var server = require('./lib/server')
   , app = require('http').createServer(server).listen(8222)
   , io = require('socket.io').listen(app)
   , transition = {};

io.sockets.on('connection', function(socket){

   socket.on('connect_client', function(data){
      var input = '';

      socket.join(data.path);

      socket.set('path', data.path);

      if(typeof transition[data.path] !== 'undefined'){
        input = transition[data.path];
      }

      var count = io.sockets.clients(data.path).length;
      var send = {count : count, input : input};

      io.sockets.in(data.path).emit('server_ready', send);

   });

   socket.on('client_input', function(input){

      socket.get('path', function(err, path){
        transition[path] = input;
        socket.broadcast.to(path).emit('server_input', input);
      });

   });

   socket.on('set_active', function(){
      socket.get('path', function(err, path){
        socket.broadcast.to(path).emit('set_inactive');
      });
   });

   socket.on('disconnect', function(){

    socket.get('path', function(err, path){

      socket.leave(path);

      var count = io.sockets.clients(path).length;

      if(count == 0){
        delete transition[path];
      }

      io.sockets.in(path).emit('disconnected', {count : count});

    });

   });

});
   <commit_msg>fixing port<commit_after>var server = require('./lib/server')
   , app = require('http').createServer(server)
   , io = require('socket.io').listen(app)
   , buffer = {}
   , PORT = process.env.PORT || 5000;

app.listen(PORT);

io.sockets.on('connection', function(socket){

   socket.on('connect_client', function(data){
      var input = '';

      socket.join(data.path);

      socket.set('path', data.path);

      if(typeof buffer[data.path] !== 'undefined'){
        input = buffer[data.path];
      }

      var count = io.sockets.clients(data.path).length;
      var send = {count : count, input : input};

      io.sockets.in(data.path).emit('server_ready', send);

   });

   socket.on('client_input', function(input){

      socket.get('path', function(err, path){
        buffer[path] = input;
        socket.broadcast.to(path).emit('server_input', input);
      });

   });

   socket.on('set_active', function(){
      socket.get('path', function(err, path){
        socket.broadcast.to(path).emit('set_inactive');
      });
   });

   socket.on('disconnect', function(){

    socket.get('path', function(err, path){

      socket.leave(path);

      var count = io.sockets.clients(path).length;

      if(count == 0){
        delete buffer[path];
      }

      io.sockets.in(path).emit('disconnected', {count : count});

    });

   });

});
   <|endoftext|>


<commit_before>var isTestNotStartedRunningOrFinished = "notStarted"; //notStarted running or finished
var linksSet = new Set();
var arrayOfPagesWithError = [];
var numberOfPagesChecked = 0;
var maxNumberOfPagesToCheck;
var lookFor = ""; //= "error"
var linksMustContain = "";
var tempLinksArray = [];
var arrayOfLinksOnPages = [];
var currentPageURL = "http://";
var errorsAndTheirLinksArray = [];
var sentNextPage;
var lastSentPage;
var testTabID;
var autoContinue;
var isTestContinueBeingForced = false;

function resetExtension(){
  isTestNotStartedRunningOrFinished = "notStarted"; //notStarted running or finished
  linksSet.clear();
//  chrome.tabs.remove([testTabID]);
  chrome.tabs.remove([testTabID], function() { });
  arrayOfPagesWithError = [];
  numberOfPagesChecked = 0;
  maxNumberOfPagesToCheck = 0;
  lookFor = "";
  linksMustContain = "";
  tempLinksArray = [];
//  tempLinksSet.clear();
  arrayOfLinksOnPages = [];
  currentPageURL = "http://";
  errorsAndTheirLinksArray = [];
  sentNextPage = "";
  lastSentPage = "";
  testTabID = null;
  clearTimeout(autoContinue);
}

chrome.runtime.onMessage.addListener(
        function(request, sender, sendResponse) {
        switch (request.greeting){
          case "What is currentPageURL":
                  sendResponse({startPageURL: currentPageURL});
                  break;
          case "Start":
                  var startURL = request.startURL;
                  sentNextPage = startURL;
                  lastSentPage = sentNextPage;
                  lookFor = request.lookFor;
                  linksMustContain = request.linksMustContain;
                  maxNumberOfPagesToCheck = request.maxNumberOfPagesToCheck;
                  linksSet.add(startURL);
                  startTest(startURL);
                  break;
          case "Stop":
                  isTestNotStartedRunningOrFinished = "finished";
                  displayFinalResults();
                  resetExtension();
                  break;
          case "Should I test?":
                  tempLinksArray = request.currentPageLinks;
                  if(shouldTestFinish()){
                    isTestNotStartedRunningOrFinished = "finished";
                  }
                  switch (isTestNotStartedRunningOrFinished){
                    case "notStarted":
                      sendResponse({shouldITest: "No"});
                      currentPageURL = request.currentPageURL;
                      break;
                    case "finished":
                      sendResponse({shouldITest: "No"});
                      displayFinalResults();
                      resetExtension();
                      break;
                    case "running":
                      if (numberOfPagesChecked == 0) {
                        testTabID = sender.tab.id;
                      }
                      if (isTestContinueBeingForced){
                        testTabID = sender.tab.id;
                        isTestContinueBeingForced = false;
                      }
                      if (testTabID == sender.tab.id){
                        tempLinksArray = removeLinksThatDontMeetRequirement(tempLinksArray, linksMustContain);
                        addUniqueURLsToLinksArray(tempLinksArray);
                        recordLinksOnCurrentPage(request.currentPageURL, tempLinksArray);
                        numberOfPagesChecked = numberOfPagesChecked + 1;
                        var linksArray = [...linksSet];
                        if (numberOfPagesChecked >= linksArray.length){
                          sentNextPage = "Stop";
                        }
                        else {
                          lastSentPage = sentNextPage;
                          sentNextPage = linksArray[numberOfPagesChecked];
                        }
                        sendResponse({shouldITest: "Yes", testFor: lookFor, nextPage: sentNextPage});
                        clearTimeout(autoContinue);
                        autoContinue = setTimeout(autoContinueTest, 3000);
                      }
                      else {
                        sendResponse({shouldITest: "No"});
                      }
                    }
                      break;
          case "Sending error":
            var errorPageToStore = lastSentPage;
            arrayOfPagesWithError.push(errorPageToStore);
            //sendResponse("Error Stored");
            if (isTestNotStartedRunningOrFinished == "finished" ){
              displayFinalResults();
              resetExtension();
            }

        }

});

function autoContinueTest(){
  let linksArray = [...linksSet];
  let continueURL = linksArray[numberOfPagesChecked];
  if (continueURL != null){
    isTestContinueBeingForced = false;
    chrome.tabs.remove([testTabID], function() { });
    chrome.tabs.create({'url': continueURL});
  } else {
    displayFinalResults();
    resetExtension();
  }
}

chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.create({'url': 'background.html'});
});

function startTest(startURL) {
    isTestNotStartedRunningOrFinished = "running";
    chrome.tabs.create({'url': startURL});
}

function shouldTestFinish(){
    if (isTestNotStartedRunningOrFinished == "notStarted"){
        return false;
    } else if (numberOfPagesChecked >= maxNumberOfPagesToCheck){
        return true;
    } else if (numberOfPagesChecked >= linksSet.size){
        addUniqueURLsToLinksArray(tempLinksArray);
        if (numberOfPagesChecked >= linksSet.size){
          return true;
        }
        return false;
    } else {
      return false;
}
}

function removeLinksThatDontMeetRequirement(_contentArray, _linksMustContain){
    let reducedLinksArray = _contentArray.filter(function(elem){
    	if (elem.includes(_linksMustContain) == true){
      	return elem;
    	}
    });
      return reducedLinksArray;
}

function addUniqueURLsToLinksArray(thisContentArray){
  let thisContentSet = new Set(thisContentArray);
  linksSet = linksSet.union(thisContentSet);
}

function displayFinalResults(){
  //linksArray = [...linksSet];
  errorsAndTheirLinksArray = matchErrorPagesWithPagesThatLinkToThem(arrayOfPagesWithError, arrayOfLinksOnPages, arrayOfPagesWithError, errorsAndTheirLinksArray );
  var resultsHTML = convertErrorsAndTheirLinksArrayToHTML(errorsAndTheirLinksArray, numberOfPagesChecked, linksSet);
  chrome.runtime.sendMessage({greeting: "display_results", HTMLtoDisplay: resultsHTML});
  resetExtension();
  notificationOfTestEnded();
}

function recordLinksOnCurrentPage(_thisPage, _thisLinksArray){
    arrayOfLinksOnPages.push([_thisPage, _thisLinksArray]);
}
function notificationOfTestEnded(){
    var opt = {
      type: "basic",
      title: "Link Skimmer",
      message: "Finished skimming your links",
      iconUrl: "SiteSkimmer32.png"
    };
    chrome.notifications.create(opt);
}

Set.prototype.union = function(setB) {
    var union = new Set(this);
    for (var elem of setB) {
        union.add(elem);
    }
    return union;
}
<commit_msg>Finished making the autoContinueTest functionality.<commit_after>var isTestNotStartedRunningOrFinished = "notStarted"; //notStarted running or finished
var linksSet = new Set();
var arrayOfPagesWithError = [];
var numberOfPagesChecked = 0;
var maxNumberOfPagesToCheck;
var lookFor = ""; //= "error"
var linksMustContain = "";
var tempLinksArray = [];
var arrayOfLinksOnPages = [];
var currentPageURL = "http://";
var errorsAndTheirLinksArray = [];
var sentNextPage;
var lastSentPage;
var testTabID;
var autoContinue;
var isTestContinueBeingForced = false;

function resetExtension(){
  isTestNotStartedRunningOrFinished = "notStarted"; //notStarted running or finished
  linksSet.clear();
try {
  chrome.tabs.remove([testTabID], function() { });
}
catch(err) {
}
  arrayOfPagesWithError = [];
  numberOfPagesChecked = 0;
  maxNumberOfPagesToCheck = 0;
  lookFor = "";
  linksMustContain = "";
  tempLinksArray = [];
  arrayOfLinksOnPages = [];
  currentPageURL = "http://";
  errorsAndTheirLinksArray = [];
  sentNextPage = "";
  lastSentPage = "";
  testTabID = null;
  clearTimeout(autoContinue);
}

chrome.runtime.onMessage.addListener(
        function(request, sender, sendResponse) {
        switch (request.greeting){
          case "What is currentPageURL":
                  sendResponse({startPageURL: currentPageURL});
                  break;
          case "Start":
                  var startURL = request.startURL;
                  sentNextPage = startURL;
                  lastSentPage = sentNextPage;
                  lookFor = request.lookFor;
                  linksMustContain = request.linksMustContain;
                  maxNumberOfPagesToCheck = request.maxNumberOfPagesToCheck;
                  linksSet.add(startURL);
                  startTest(startURL);
                  break;
          case "Stop":
                  isTestNotStartedRunningOrFinished = "finished";
                  displayFinalResults();
                  resetExtension();
                  break;
          case "Should I test?":
                  tempLinksArray = request.currentPageLinks;
                  if(shouldTestFinish()){
                    isTestNotStartedRunningOrFinished = "finished";
                  }
                  switch (isTestNotStartedRunningOrFinished){
                    case "notStarted":
                      sendResponse({shouldITest: "No"});
                      currentPageURL = request.currentPageURL;
                      break;
                    case "finished":
                      sendResponse({shouldITest: "No"});
                      displayFinalResults();
                      resetExtension();
                      break;
                    case "running":
                      if (numberOfPagesChecked == 0) {
                        testTabID = sender.tab.id;
                      }
                      if (isTestContinueBeingForced){
                        testTabID = sender.tab.id;
                        isTestContinueBeingForced = false;
                      }
                      if (testTabID == sender.tab.id){
                        tempLinksArray = removeLinksThatDontMeetRequirement(tempLinksArray, linksMustContain);
                        addUniqueURLsToLinksArray(tempLinksArray);
                        recordLinksOnCurrentPage(request.currentPageURL, tempLinksArray);
                        numberOfPagesChecked = numberOfPagesChecked + 1;
                        var linksArray = [...linksSet];
                        if (numberOfPagesChecked >= linksArray.length){
                          sentNextPage = "Stop";
                        }
                        else {
                          lastSentPage = sentNextPage;
                          sentNextPage = linksArray[numberOfPagesChecked];
                        }
                        sendResponse({shouldITest: "Yes", testFor: lookFor, nextPage: sentNextPage});
                        clearTimeout(autoContinue);
                        autoContinue = setTimeout(autoContinueTest, 6000);
                      }
                      else {
                        sendResponse({shouldITest: "No"});
                      }
                    }
                      break;
          case "Sending error":
            var errorPageToStore = lastSentPage;
            arrayOfPagesWithError.push(errorPageToStore);
            //sendResponse("Error Stored");
            if (isTestNotStartedRunningOrFinished == "finished" ){
              displayFinalResults();
              resetExtension();
            }

        }

});

function autoContinueTest(){
  let linksArray = [...linksSet];
  let continueURL = linksArray[numberOfPagesChecked];
  numberOfPagesChecked += 1;
  if (continueURL != null){
    isTestContinueBeingForced = true;
    try {    chrome.tabs.remove([testTabID], function() { });
  } catch(err) {}
    chrome.tabs.create({'url': continueURL});
  } else {
    displayFinalResults();
    resetExtension();
  }
}

chrome.browserAction.onClicked.addListener(function(tab) {
    chrome.tabs.create({'url': 'background.html'});
});

function startTest(startURL) {
    isTestNotStartedRunningOrFinished = "running";
    chrome.tabs.create({'url': startURL});
}

function shouldTestFinish(){
    if (isTestNotStartedRunningOrFinished == "notStarted"){
        return false;
    } else if (numberOfPagesChecked >= maxNumberOfPagesToCheck){
        return true;
    } else if (numberOfPagesChecked >= linksSet.size){
        addUniqueURLsToLinksArray(tempLinksArray);
        if (numberOfPagesChecked >= linksSet.size){
          return true;
        }
        return false;
    } else {
      return false;
}
}

function removeLinksThatDontMeetRequirement(_contentArray, _linksMustContain){
    let reducedLinksArray = _contentArray.filter(function(elem){
    	if (elem.includes(_linksMustContain) == true){
      	return elem;
    	}
    });
      return reducedLinksArray;
}

function addUniqueURLsToLinksArray(thisContentArray){
  let thisContentSet = new Set(thisContentArray);
  linksSet = linksSet.union(thisContentSet);
}

function displayFinalResults(){
  //linksArray = [...linksSet];
  errorsAndTheirLinksArray = matchErrorPagesWithPagesThatLinkToThem(arrayOfPagesWithError, arrayOfLinksOnPages, arrayOfPagesWithError, errorsAndTheirLinksArray );
  var resultsHTML = convertErrorsAndTheirLinksArrayToHTML(errorsAndTheirLinksArray, numberOfPagesChecked, linksSet);
  chrome.runtime.sendMessage({greeting: "display_results", HTMLtoDisplay: resultsHTML});
  resetExtension();
  notificationOfTestEnded();
}

function recordLinksOnCurrentPage(_thisPage, _thisLinksArray){
    arrayOfLinksOnPages.push([_thisPage, _thisLinksArray]);
}
function notificationOfTestEnded(){
    var opt = {
      type: "basic",
      title: "Link Skimmer",
      message: "Finished skimming your links",
      iconUrl: "SiteSkimmer32.png"
    };
    chrome.notifications.create(opt);
}

Set.prototype.union = function(setB) {
    var union = new Set(this);
    for (var elem of setB) {
        union.add(elem);
    }
    return union;
}
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var questions = require('./routes/questions');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.options('/questions', function(req, res){
  res.header("Access-Control-Allow-Origin", "http://localhost:9000");
  res.header('Access-Control-Allow-Headers', 'X-Requested-With,,Content-Type, Authorization');
  res.end('');
});

// Add headers
app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:9000');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type,Authorization');
    next();
});

app.get('/questions', questions.index);
app.post('/questions', questions.create);
app.put('/questions/:id', questions.upvote);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;
<commit_msg>error middleware returns json<commit_after>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var questions = require('./routes/questions');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.options('/questions', function(req, res){
  res.header("Access-Control-Allow-Origin", "http://localhost:9000");
  res.header('Access-Control-Allow-Headers', 'X-Requested-With,,Content-Type, Authorization');
  res.end('');
});

// Add headers
app.use(function (req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:9000');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type,Authorization');
    next();
});

app.get('/questions', questions.index);
app.post('/questions', questions.create);
app.put('/questions/:id', questions.upvote);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.send({
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.send({
        message: err.message,
        error: {}
    });
});

module.exports = app;
<|endoftext|>


<commit_before>/**
 * StopFlash
 *
 * https://github.com/JWhile/StopFlash
 *
 * background.js
 */

// class BackgroundFlashCollection
function BackgroundFlashCollection(id, port)
{
    this.id = id; // :int

    this.port = port; // :chrome.runtime.Port

    var self = this;

    port.onDisconnect.addListener(function()
    {
        self.port = null;
    });
};

// class BackgroundFlashData
function BackgroundFlashData(id)
{
    this.id = id; // :int

    this.data = []; // :Array<Object>

    this.collections = []; // :Array<BackgroundFlashCollection>

    this.popupPort = null; // :chrome.runtime.Port
}
// function setData(Object data):void
BackgroundFlashData.prototype.setData = function(data)
{
    if(data.length > 0)
    {
        Array.prototype.unshift.apply(this.data, data);

        this.sendToPopup();
    }
};
// function setPopup(chrome.runtime.Port popupPort):void
BackgroundFlashData.prototype.setPopup = function(popupPort)
{
    this.popupPort = popupPort;

    var self = this;

    this.popupPort.onDisconnect.addListener(function()
    {
        self.popupPort = null;
    });

    this.sendToPopup();
};
// function setContentScript(chrome.runtime.Port contentPort):void
BackgroundFlashData.prototype.setContentScript = function(contentPort)
{
    this.collections.push(new BackgroundFlashCollection(++collectionId, contentPort));

    contentPort.postMessage({'stopflashWhitelist': whitelist, 'stopflashContentId': 0});
};
// function sendToPopup():void
BackgroundFlashData.prototype.sendToPopup = function()
{
    if(this.popupPort != null)
    {
        this.popupPort.postMessage({'stopflashData': this.data});
    }
};
// function sendToContent(Object data):void
BackgroundFlashData.prototype.sendToContent = function(data)
{
    for(var i = 0; i < this.collections.length; ++i)
    {
        this.collections[i].port.postMessage(data);
    }
};
// function clear():void
BackgroundFlashData.prototype.clear = function()
{
    this.data = null;

    if(this.popupPort != null)
    {
        this.popupPort.disconnect();
    }

    this.popupPort = null;

    if(this.collections.length > 0)
    {
        for(var i = 0; i < this.collections.length; ++i)
        {
            this.collections[i].port.disconnect();
        }
    }

    this.collections = [];
};

var flashData = []; // :Array<BackgroundFlashData>
var whitelist = []; // :Array<String>
var collectionId = 0; // :int

// function getFlashData(int id):BackgroundFlashData
var getFlashData = function(id)
{
    for(var i = 0; i < flashData.length; ++i)
    {
        if(flashData[i].id === id)
        {
            return flashData[i];
        }
    }

    return null;
};

chrome.runtime.onConnect.addListener(function(port)
{
    if(port.name === 'stopflashContentScript' && port.sender.tab != null)
    {
        var data = null;

        port.onMessage.addListener(function(rep)
        {
            if(rep['stopflashInit'])
            {
                data = getFlashData(port.sender.tab.id);

                if(data != null)
                {
                    if(rep['stopflashIsMainFrame'])
                    {
                        data.clear();
                    }
                }
                else
                {
                    data = new BackgroundFlashData(port.sender.tab.id);

                    flashData.push(data);
                }

                data.setContentScript(port);
            }

            if(rep['stopflashHaveChange'])
            {
                if(rep['stopflashIsMainFrame'])
                {
                    data.data = [];
                }

                data.sendToContent({'stopflashDataUpdate': true});
            }

            if(rep['stopflashDataUpdate'] && rep['stopflashData'])
            {
                data.setData(rep.stopflashData);
            }
        });
    }
    else if(port.name === 'stopflashPopup')
    {
        var data = null;

        port.onMessage.addListener(function(rep)
        {
            if(rep['stopflashInit'])
            {
                data = getFlashData(rep['stopflashInit']);

                if(data != null)
                {
                    data.setPopup(port);
                }
            }

            if(rep['stopflashBlock'])
            {

                data.sendToContent({'stopflashBlock': rep['stopflashBlock']});
            }

            if(rep['stopflashUnblock'])
            {
                data.sendToContent({'stopflashUnblock': rep['stopflashUnblock']});
            }
        });
    }
});
<commit_msg>Move collectionId into BackgroundFlashData<commit_after>/**
 * StopFlash
 *
 * https://github.com/JWhile/StopFlash
 *
 * background.js
 */

// class BackgroundFlashCollection
function BackgroundFlashCollection(id, port)
{
    this.id = id; // :int

    this.port = port; // :chrome.runtime.Port

    var self = this;

    port.onDisconnect.addListener(function()
    {
        self.port = null;
    });
};

// class BackgroundFlashData
function BackgroundFlashData(id)
{
    this.id = id; // :int

    this.data = []; // :Array<Object>

    this.collectionId = 0; // :int

    this.collections = []; // :Array<BackgroundFlashCollection>

    this.popupPort = null; // :chrome.runtime.Port
}
// function setData(Object data):void
BackgroundFlashData.prototype.setData = function(data)
{
    if(data.length > 0)
    {
        Array.prototype.unshift.apply(this.data, data);

        this.sendToPopup();
    }
};
// function setPopup(chrome.runtime.Port popupPort):void
BackgroundFlashData.prototype.setPopup = function(popupPort)
{
    this.popupPort = popupPort;

    var self = this;

    this.popupPort.onDisconnect.addListener(function()
    {
        self.popupPort = null;
    });

    this.sendToPopup();
};
// function setContentScript(chrome.runtime.Port contentPort):void
BackgroundFlashData.prototype.setContentScript = function(contentPort)
{
    this.collections.push(new BackgroundFlashCollection(++this.collectionId, contentPort));

    contentPort.postMessage({'stopflashWhitelist': whitelist, 'stopflashContentId': 0});
};
// function sendToPopup():void
BackgroundFlashData.prototype.sendToPopup = function()
{
    if(this.popupPort != null)
    {
        this.popupPort.postMessage({'stopflashData': this.data});
    }
};
// function sendToContent(Object data):void
BackgroundFlashData.prototype.sendToContent = function(data)
{
    for(var i = 0; i < this.collections.length; ++i)
    {
        this.collections[i].port.postMessage(data);
    }
};
// function clear():void
BackgroundFlashData.prototype.clear = function()
{
    this.data = null;

    if(this.popupPort != null)
    {
        this.popupPort.disconnect();
    }

    this.popupPort = null;

    if(this.collections.length > 0)
    {
        for(var i = 0; i < this.collections.length; ++i)
        {
            this.collections[i].port.disconnect();
        }
    }

    this.collections = [];
};

var flashData = []; // :Array<BackgroundFlashData>
var whitelist = []; // :Array<String>

// function getFlashData(int id):BackgroundFlashData
var getFlashData = function(id)
{
    for(var i = 0; i < flashData.length; ++i)
    {
        if(flashData[i].id === id)
        {
            return flashData[i];
        }
    }

    return null;
};

chrome.runtime.onConnect.addListener(function(port)
{
    if(port.name === 'stopflashContentScript' && port.sender.tab != null)
    {
        var data = null;

        port.onMessage.addListener(function(rep)
        {
            if(rep['stopflashInit'])
            {
                data = getFlashData(port.sender.tab.id);

                if(data != null)
                {
                    if(rep['stopflashIsMainFrame'])
                    {
                        data.clear();
                    }
                }
                else
                {
                    data = new BackgroundFlashData(port.sender.tab.id);

                    flashData.push(data);
                }

                data.setContentScript(port);
            }

            if(rep['stopflashHaveChange'])
            {
                if(rep['stopflashIsMainFrame'])
                {
                    data.data = [];
                }

                data.sendToContent({'stopflashDataUpdate': true});
            }

            if(rep['stopflashDataUpdate'] && rep['stopflashData'])
            {
                data.setData(rep.stopflashData);
            }
        });
    }
    else if(port.name === 'stopflashPopup')
    {
        var data = null;

        port.onMessage.addListener(function(rep)
        {
            if(rep['stopflashInit'])
            {
                data = getFlashData(rep['stopflashInit']);

                if(data != null)
                {
                    data.setPopup(port);
                }
            }

            if(rep['stopflashBlock'])
            {

                data.sendToContent({'stopflashBlock': rep['stopflashBlock']});
            }

            if(rep['stopflashUnblock'])
            {
                data.sendToContent({'stopflashUnblock': rep['stopflashUnblock']});
            }
        });
    }
});
<|endoftext|>


<commit_before>/*global window:false */
( function( $, mw ) {
	'use strict';

	mw.echo.overlay = {

		'updateCount' : function( newCount ) {
			// Accomodate '10' or '100+'. Numbers need to be
			// passed as numbers for correct behavior of '0'.
			if ( !isNaN( newCount ) ) {
				newCount = Number( newCount );
			}

			if ( mw.echo.overlay.configuration['notifications-link-full'] ) {
				$( '#pt-notifications > a' )
					.text( mw.msg( 'echo-link' ) )
					.badge( newCount, true, true );
			} else {
				$( '#pt-notifications > a' )
					.addClass( 'mw-echo-short-link' )
					.text( '' )
					.badge( newCount, true, true );
			}

			mw.echo.overlay.notification_count = newCount;
		},

		'configuration' : mw.config.get( 'wgEchoOverlayConfiguration' ),

		'buildOverlay' : function( callback ) {
			var $overlay = $( '

' ).addClass( 'mw-echo-overlay' ),
				$link = $( '#pt-notifications a' ),
				$prefLink = $( '#pt-preferences a' ),
				count = 0;
			var Api = new mw.Api();
			// Set notification limit based on height of the window
			var notificationLimit = Math.floor( ( $( window ).height() - 134 ) / 85 );

			if ( notificationLimit < 1 ) {
				notificationLimit = 1;
			}

			Api.get( {
				'action' : 'query',
				'meta' : 'notifications',
				'notformat' : 'flyout',
				'notlimit' : notificationLimit,
				'notprop' : 'index|list|count'
			}, {
				'ok' : function( result ) {
					var notifications = result.query.notifications,
						unread = [],
						unreadTotalCount = result.query.notifications.count,
						$title = $( '

' ),
						$ul = $( '

' ),
						titleText = '';

					$ul.css( 'max-height', notificationLimit * 95 + 'px' );
					$.each( notifications.index, function( index, id ) {
						var data = notifications.list[id];
						var $li = $( '

' )
								.data( 'details', data )
								.data( 'id', id )
								.attr( 'data-notification-category', data.category )
								.addClass( 'mw-echo-notification' )
								.append( data['*'] )
								.appendTo( $ul );

						if ( !data.read ) {
							$li.addClass( 'mw-echo-unread' );
							unread.push( id );
						}

						// Set up each individual notification with a close box and dismiss
						// interface if it is dismissable.
						if ( $li.find( '.mw-echo-dismiss' ).length ) {
							mw.echo.setUpDismissability( $li );
						}
					} );

					if ( notifications.index.length > 0 ) {
						if ( unreadTotalCount > unread.length ) {
							titleText = mw.msg( 'echo-overlay-title-overflow', unread.length, unreadTotalCount );
						} else {
							titleText =  mw.msg( 'echo-overlay-title' );
						}
					} else {
						titleText = mw.msg( 'echo-none' );
					}
					$title.text( titleText );
					$title.appendTo( $overlay );

					if ( $ul.find( 'li' ).length ) {
						$ul.appendTo( $overlay );
					}

					var $overlayFooter = $( '
' )
						.attr( 'id', 'mw-echo-overlay-footer' );

					// add link to notifications archive
					$overlayFooter.append(
						$link
							.clone()
							.attr( 'id', 'mw-echo-overlay-link' )
							.text( mw.msg( 'echo-overlay-link' ) )
					);

					// add link to notification preferences
					$overlayFooter.append(
						$prefLink
							.clone()
							.attr( 'id', 'mw-echo-overlay-pref-link' )
							.attr( 'href', $prefLink.attr( 'href' ) + '#mw-prefsection-echo' )
					);

					$overlay.append( $overlayFooter );

					callback( $overlay );

					// only need to mark as read if there is unread item
					if ( unread.length > 0 ) {
						Api.get( {
							'action' : 'query',
							'meta' : 'notifications',
							'notmarkread' : unread.join( '|' ),
							'notprop' : 'count'
						}, {
							'ok' : function( result ) {
								if ( result.query.notifications.count !== undefined ) {
									count = result.query.notifications.count;
									mw.echo.overlay.updateCount( count );
								}
							}
						} );
					}
				},
				'err' : function() {
					window.location.href = $link.attr( 'href' );
				}
			} );
		}
	};

	mw.echo.overlay.notification_count = mw.echo.overlay.configuration['notification-count'];

	$( function() {
		mw.echo.overlay.updateCount( mw.echo.overlay.notification_count );

		var $link = $( '#pt-notifications a' );
		if ( ! $link.length ) {
			return;
		}

		$link.click( function( e ) {
			e.preventDefault();
			var $target = $( e.target );
			// If the user clicked on the overlay or any child,
			//  ignore the click
			if ( $target.hasClass( 'mw-echo-overlay' ) ||
				$target.is( 'mw-echo-overlay *' )
			) {
				return;
			}

			var $overlay = $( '.mw-echo-overlay' );

			if ( $overlay.length ) {
				$overlay.fadeOut( 'fast',
					function() { $overlay.remove(); }
				);
				return;
			}

			$overlay = mw.echo.overlay.buildOverlay(
				function( $overlay ) {
					$overlay
						.hide()
						.appendTo( $( '#pt-notifications' ) );
					// Create the pokey (aka chevron)
					$( '.mw-echo-overlay' ).before( $( '
' ).addClass( 'mw-echo-overlay-pokey' ) );
					// Show the notifications overlay
					$overlay.show();
				} );
		} );

		$( 'body' ).click( function( e ) {
			if ( ! $( e.target ).is( '.mw-echo-overlay, .mw-echo-overlay *, .mw-echo-overlay-pokey' ) ) {
				$( '.mw-echo-overlay, .mw-echo-overlay-pokey' ).fadeOut( 'fast',
					function() { $( this ).remove(); }
				);
			}
		} );
	} );
} )( jQuery, mediaWiki );
<commit_msg>Better limits on number of notifications in the flyout<commit_after>/*global window:false */
( function( $, mw ) {
	'use strict';

	mw.echo.overlay = {

		'updateCount' : function( newCount ) {
			// Accomodate '10' or '100+'. Numbers need to be
			// passed as numbers for correct behavior of '0'.
			if ( !isNaN( newCount ) ) {
				newCount = Number( newCount );
			}

			if ( mw.echo.overlay.configuration['notifications-link-full'] ) {
				$( '#pt-notifications > a' )
					.text( mw.msg( 'echo-link' ) )
					.badge( newCount, true, true );
			} else {
				$( '#pt-notifications > a' )
					.addClass( 'mw-echo-short-link' )
					.text( '' )
					.badge( newCount, true, true );
			}

			mw.echo.overlay.notification_count = newCount;
		},

		'configuration' : mw.config.get( 'wgEchoOverlayConfiguration' ),

		'buildOverlay' : function( callback ) {
			var $overlay = $( '

' ).addClass( 'mw-echo-overlay' ),
				$link = $( '#pt-notifications a' ),
				$prefLink = $( '#pt-preferences a' ),
				count = 0;
			var Api = new mw.Api();
			// Set notification limit based on height of the window
			var notificationLimit = Math.floor( ( $( window ).height() - 134 ) / 90 );

			if ( notificationLimit < 1 ) {
				notificationLimit = 1;
			} else if ( notificationLimit > 8 ) {
				notificationLimit = 8;
			}

			Api.get( {
				'action' : 'query',
				'meta' : 'notifications',
				'notformat' : 'flyout',
				'notlimit' : notificationLimit,
				'notprop' : 'index|list|count'
			}, {
				'ok' : function( result ) {
					var notifications = result.query.notifications,
						unread = [],
						unreadTotalCount = result.query.notifications.count,
						$title = $( '

' ),
						$ul = $( '

' ),
						titleText = '';

					$ul.css( 'max-height', notificationLimit * 95 + 'px' );
					$.each( notifications.index, function( index, id ) {
						var data = notifications.list[id];
						var $li = $( '

' )
								.data( 'details', data )
								.data( 'id', id )
								.attr( 'data-notification-category', data.category )
								.addClass( 'mw-echo-notification' )
								.append( data['*'] )
								.appendTo( $ul );

						if ( !data.read ) {
							$li.addClass( 'mw-echo-unread' );
							unread.push( id );
						}

						// Set up each individual notification with a close box and dismiss
						// interface if it is dismissable.
						if ( $li.find( '.mw-echo-dismiss' ).length ) {
							mw.echo.setUpDismissability( $li );
						}
					} );

					if ( notifications.index.length > 0 ) {
						if ( unreadTotalCount > unread.length ) {
							titleText = mw.msg( 'echo-overlay-title-overflow', unread.length, unreadTotalCount );
						} else {
							titleText =  mw.msg( 'echo-overlay-title' );
						}
					} else {
						titleText = mw.msg( 'echo-none' );
					}
					$title.text( titleText );
					$title.appendTo( $overlay );

					if ( $ul.find( 'li' ).length ) {
						$ul.appendTo( $overlay );
					}

					var $overlayFooter = $( '
' )
						.attr( 'id', 'mw-echo-overlay-footer' );

					// add link to notifications archive
					$overlayFooter.append(
						$link
							.clone()
							.attr( 'id', 'mw-echo-overlay-link' )
							.text( mw.msg( 'echo-overlay-link' ) )
					);

					// add link to notification preferences
					$overlayFooter.append(
						$prefLink
							.clone()
							.attr( 'id', 'mw-echo-overlay-pref-link' )
							.attr( 'href', $prefLink.attr( 'href' ) + '#mw-prefsection-echo' )
					);

					$overlay.append( $overlayFooter );

					callback( $overlay );

					// only need to mark as read if there is unread item
					if ( unread.length > 0 ) {
						Api.get( {
							'action' : 'query',
							'meta' : 'notifications',
							'notmarkread' : unread.join( '|' ),
							'notprop' : 'count'
						}, {
							'ok' : function( result ) {
								if ( result.query.notifications.count !== undefined ) {
									count = result.query.notifications.count;
									mw.echo.overlay.updateCount( count );
								}
							}
						} );
					}
				},
				'err' : function() {
					window.location.href = $link.attr( 'href' );
				}
			} );
		}
	};

	mw.echo.overlay.notification_count = mw.echo.overlay.configuration['notification-count'];

	$( function() {
		mw.echo.overlay.updateCount( mw.echo.overlay.notification_count );

		var $link = $( '#pt-notifications a' );
		if ( ! $link.length ) {
			return;
		}

		$link.click( function( e ) {
			e.preventDefault();
			var $target = $( e.target );
			// If the user clicked on the overlay or any child,
			//  ignore the click
			if ( $target.hasClass( 'mw-echo-overlay' ) ||
				$target.is( 'mw-echo-overlay *' )
			) {
				return;
			}

			var $overlay = $( '.mw-echo-overlay' );

			if ( $overlay.length ) {
				$overlay.fadeOut( 'fast',
					function() { $overlay.remove(); }
				);
				return;
			}

			$overlay = mw.echo.overlay.buildOverlay(
				function( $overlay ) {
					$overlay
						.hide()
						.appendTo( $( '#pt-notifications' ) );
					// Create the pokey (aka chevron)
					$( '.mw-echo-overlay' ).before( $( '
' ).addClass( 'mw-echo-overlay-pokey' ) );
					// Show the notifications overlay
					$overlay.show();
				} );
		} );

		$( 'body' ).click( function( e ) {
			if ( ! $( e.target ).is( '.mw-echo-overlay, .mw-echo-overlay *, .mw-echo-overlay-pokey' ) ) {
				$( '.mw-echo-overlay, .mw-echo-overlay-pokey' ).fadeOut( 'fast',
					function() { $( this ).remove(); }
				);
			}
		} );
	} );
} )( jQuery, mediaWiki );
<|endoftext|>


<commit_before>var _ = require('lodash');
var express = require('express');
var app = express();

var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
app.set('port', (process.env.PORT || 5000));

app.get('/', function(request, response) {
  response.send('Hello World!');
});

app.post('/callback', function(request, response) {

    console.log(req.body);
    var result = req.body.result;
    console.log(result);

    _.each(result, function(msg){
        console.log(msg);
    })

    // var request = require('superagent');
    // request
    //     .post('https://trialbot-api.line.me/v1/events')
    //     .end(function(res){
    //       if (res.ok) {
    //         console.log(res.body.name);
    //       } else {
    //             console.log('error');
    //       }
    //     });

});

app.listen(app.get('port'), function() {
  console.log("Node app is running at localhost:" + app.get('port'))
});
<commit_msg>debugging2<commit_after>var _ = require('lodash');
var express = require('express');
var app = express();

var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
app.set('port', (process.env.PORT || 5000));

app.get('/', function(req, res) {
  res.send('Hello World!');
});

app.post('/callback', function(req, res) {

    console.log(req.body);
    var result = req.body.result;
    console.log(result);

    _.each(result, function(msg){
        console.log(msg);
    })

    // var request = require('superagent');
    // request
    //     .post('https://trialbot-api.line.me/v1/events')
    //     .end(function(res){
    //       if (res.ok) {
    //         console.log(res.body.name);
    //       } else {
    //             console.log('error');
    //       }
    //     });

});

app.listen(app.get('port'), function() {
  console.log("Node app is running at localhost:" + app.get('port'))
});
<|endoftext|>


<commit_before><commit_msg>bug  3804<commit_after><|endoftext|>