<commit_before>const APP_PORT = 8081;
//var JQUERY_JS = "jquery-2.1.4.min.js";
var JQUERY_JS = "jquery-3.2.1.min.js";
var PAGE_JS = "page.js";
var apiUrl = 'http://localhost:' + APP_PORT + '/';

var pageErrors = [];
let networkRequests = new Map(); // map[requestId, {requestData}]
var activeFrameId = 0;
var contentScriptCode = '';

chrome.runtime.onMessage.addListener(pageErrorsListener);

getFileContents(JQUERY_JS, function (contents1) {
    getFileContents(PAGE_JS, function (content2) {
        contentScriptCode = contents1 + content2;
        setupSocketClient(apiUrl);
    });
});

function setupSocketClient(apiUrl) {
    console.log('Initializing websocket client ...');

    var socket = io.connect(apiUrl);

    socket.on('cmd', function (data) {
        console.log('cmd: ' + data.cmd);
        data.frameId = activeFrameId;
        runActionInBrowser(socket, data);
    });

    // extension is started and ready - notify the server    
    socket.emit('chrome_ready');
}

function getFileContents(filename, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', chrome.extension.getURL(filename), true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
            callback(xhr.responseText);
        }
    };
    xhr.send();
}

function runActionInBrowser(socket, data) {
    switch (data.cmd) {
        case "get_views_info":
            var retval = [];
            chrome.windows.getAll({}, function (windows) {
                var remainingWindows = windows.length;

                windows.forEach(function (window) {
                    console.log('chrome.windows.getAll - wid=', window.id);

                    chrome.tabs.query({ windowId: window.id }, function (tabs) {
                        remainingWindows--;
                        tabs.forEach(function (tab) {
                            var viewInfo = {
                                id: tab.id,
                                index: tab.index,
                                isActive: tab.active,
                                url: tab.url, title:
                                    tab.title,
                                windowId: window.id,
                                windowType: window.type,
                                top: window.top,
                                left: window.left,
                                width: window.width,
                                height: window.height,
                                state: window.state
                            };
                            retval.push(viewInfo);
                        });

                        if (remainingWindows === 0) {
                            // we are done!
                            data.retVal = retval;
                            socket.emit('cmd_out', data);
                            console.log('--' + data.cmd + ' done:', data);
                        }
                    });
                });
            });

            break;

        case "set_active_view":
            chrome.tabs.update(data.tabId, { active: true }, function (tabs) {

                if (chrome.runtime.lastError) {
                    console.log('--' + data.cmd + ' error');
                    data.error_code = 500;
                    data.error_message = chrome.runtime.lastError.message;
                    socket.emit('cmd_out', data);
                    return;
                }

                socket.emit('cmd_out', data);
                console.log('--' + data.cmd + ' done:', data);
            });
            break;

        case "close_view":
            chrome.tabs.remove(data.tabId, function (tabs) {

                if (chrome.runtime.lastError) {
                    console.log('--' + data.cmd + ' error');
                    data.error_code = 500;
                    data.error_message = chrome.runtime.lastError.message;
                    socket.emit('cmd_out', data);
                    return;
                }

                socket.emit('cmd_out', data);
                console.log('--' + data.cmd + ' done:', data);
            });
            break;

        case "set_views_info":
            chrome.windows.getCurrent(function (wind) {
                var updateInfo = {};
                // data is passed as string, we cannot use || since a top/left position of (0,0) should be supported
                if (data.top)
                    updateInfo.top = parseInt(data.top)
                if (data.left)
                    updateInfo.left = parseInt(data.left)
                if (data.width)
                    updateInfo.width = parseInt(data.width)
                if (data.height)
                    updateInfo.height = parseInt(data.height)
                if (data.state)
                    updateInfo.state = data.state

                chrome.windows.update(wind.id, updateInfo, function (window) {
                    socket.emit('cmd_out', data);
                });
            });
            break;

        case "get_errors":
            data.retVal = pageErrors;
            socket.emit('cmd_out', data);
            console.log('--' + data.cmd + ' done:', data);
            break;

        case "clear_errors":
            pageErrors = [];
            socket.emit('cmd_out', data);
            console.log('--' + data.cmd + ' done:', data);
            break;

        case "pause":
            handlePause(socket, data);
            break;

        default:
            // runs all other actions in the current window & tab
            findActiveTabAndRunAction(socket, data);
    }
}

function handlePause(socket, data) {
    setExtensionIcon(true);
    chrome.browserAction.onClicked.addListener(function (tab) {
        socket.emit('cmd_out', data);
        setExtensionIcon();
    });
}

function findActiveTabAndRunAction(socket, data) {
    chrome.windows.getCurrent({}, function (window) {
        try {
            chrome.tabs.query({ active: true }, function (tabs) {
                tab = tabs[0]; // only work with the active tab - and there is only one active tab!             
                runActionInActivePage(socket, tab, data);
            });
        }
        catch (err) {
            console.log('-- ERROR: ' + err.message);
            data.error_code = 500;
            data.error_message = err.message;
            socket.emit('cmd_out', data);
        }
    });
}

function runActionInActivePage(socket, tab, data) {
    if (tab === undefined) {
        console.log('--' + data.cmd + ' error');
        data.error_code = 501;
        data.error_message = 'ERROR: Unable to find the active tab';
        socket.emit('cmd_out', data);
        return;
    }

    switch (data.cmd) {
        case "get_url":
            data.retVal = tab.url;
            socket.emit('cmd_out', data);
            console.log('--' + data.cmd + ' done');
            break;

        case "set_url":
            function tabUpdatedListener(tabId, changeInfo, tab) {
                console.log('--status=' + changeInfo.status + ' url=' + tab.url);
                if (changeInfo.status == 'complete' && tab.url !== 'about:blank') { /* timing issue where about:blank will be 'complete' before socket connection occurs before the about:blank tab is created*/
                    chrome.tabs.onUpdated.removeListener(tabUpdatedListener);
                    socket.emit('cmd_out', data);
                    console.log('--' + data.cmd + ' done');
                }
            }

            chrome.tabs.onUpdated.addListener(tabUpdatedListener);

            // updates the url - response will be sent after the page load is complete - see above
            chrome.tabs.update(tab.id, { url: data.value });
            break;

        case "screenshot":
            chrome.tabs.captureVisibleTab(tab.windowId, { format: "jpeg", quality: 70 }, function (dataUrl) {
                data.retVal = dataUrl;
                socket.emit('cmd_out', data);
                console.log('--' + data.cmd + ' done');
            });
            break;

        case "enable_network_stats":
            parseIncomingNetworkMessage();
            socket.emit('cmd_out', data);
            break;

        case "get_network_stats_latest_timestamp":
        case "get_network_stats":
            let networkStatsArray = Array.from(networkRequests.values());
            switch (data.cmd) {
                case "get_network_stats_latest_timestamp":
                    const latestTimeStamp = networkStatsArray.reduce((last, current) => current.startTime > last ? current.startTime : last, 0);
                    data.retVal = latestTimeStamp;
                    break;

                case "get_network_stats":
                    if (data.path) {
                        // lowerbound value specified in the path, for instance: http://restbot/955664.555762?get_network_stats instead of http://restbot/?get_network_stats
                        const lowerBound = parseFloat(data.path);
                        networkStatsArray = networkStatsArray.filter(current => current.startTime > lowerBound);
                    }

                    const sortedNetworkStats = networkStatsArray.sort((a, b) => {
                        if (a.startTime > b.startTime) {
                            return 1;
                        }
                        if (a.startTime < b.startTime) {
                            return -1;
                        }
                        return 0;
                    });
                    data.retVal = sortedNetworkStats;
                    break;
            }

            socket.emit('cmd_out', data);
            break;

        case "fullpage_screenshot":
            var tabId = tab.id;
            var debuggeeId = { tabId: tabId };<commit_msg>- refactor<commit_after>const APP_PORT = 8081;
//var JQUERY_JS = "jquery-2.1.4.min.js";
var JQUERY_JS = "jquery-3.2.1.min.js";
var PAGE_JS = "page.js";
var apiUrl = 'http://localhost:' + APP_PORT + '/';

var pageErrors = [];
let networkRequests = new Map(); // map[requestId, {requestData}]
var activeFrameId = 0;
var contentScriptCode = '';

chrome.runtime.onMessage.addListener(pageErrorsListener);

getFileContents(JQUERY_JS, function (contents1) {
    getFileContents(PAGE_JS, function (content2) {
        contentScriptCode = contents1 + content2;
        setupSocketClient(apiUrl);
    });
});

function setupSocketClient(apiUrl) {
    console.log('Initializing websocket client ...');

    var socket = io.connect(apiUrl);

    socket.on('cmd', function (data) {
        console.log('cmd: ' + data.cmd);
        data.frameId = activeFrameId;
        runActionInBrowser(socket, data);
    });

    // extension is started and ready - notify the server    
    socket.emit('chrome_ready');
}

function getFileContents(filename, callback) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', chrome.extension.getURL(filename), true);
    xhr.onreadystatechange = function () {
        if (xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
            callback(xhr.responseText);
        }
    };
    xhr.send();
}

function runActionInBrowser(socket, data) {
    switch (data.cmd) {
        case "get_views_info":
            var retval = [];
            chrome.windows.getAll({}, function (windows) {
                var remainingWindows = windows.length;

                windows.forEach(function (window) {
                    console.log('chrome.windows.getAll - wid=', window.id);

                    chrome.tabs.query({ windowId: window.id }, function (tabs) {
                        remainingWindows--;
                        tabs.forEach(function (tab) {
                            var viewInfo = {
                                id: tab.id,
                                index: tab.index,
                                isActive: tab.active,
                                url: tab.url, title:
                                    tab.title,
                                windowId: window.id,
                                windowType: window.type,
                                top: window.top,
                                left: window.left,
                                width: window.width,
                                height: window.height,
                                state: window.state
                            };
                            retval.push(viewInfo);
                        });

                        if (remainingWindows === 0) {
                            // we are done!
                            data.retVal = retval;
                            socket.emit('cmd_out', data);
                            console.log('--' + data.cmd + ' done:', data);
                        }
                    });
                });
            });

            break;

        case "set_active_view":
            chrome.tabs.update(data.tabId, { active: true }, function (tabs) {

                if (chrome.runtime.lastError) {
                    console.log('--' + data.cmd + ' error');
                    data.error_code = 500;
                    data.error_message = chrome.runtime.lastError.message;
                    socket.emit('cmd_out', data);
                    return;
                }

                socket.emit('cmd_out', data);
                console.log('--' + data.cmd + ' done:', data);
            });
            break;

        case "close_view":
            chrome.tabs.remove(data.tabId, function (tabs) {

                if (chrome.runtime.lastError) {
                    console.log('--' + data.cmd + ' error');
                    data.error_code = 500;
                    data.error_message = chrome.runtime.lastError.message;
                    socket.emit('cmd_out', data);
                    return;
                }

                socket.emit('cmd_out', data);
                console.log('--' + data.cmd + ' done:', data);
            });
            break;

        case "set_views_info":
            chrome.windows.getCurrent(function (wind) {
                var updateInfo = {};
                // data is passed as string, we cannot use || since a top/left position of (0,0) should be supported
                if (data.top)
                    updateInfo.top = parseInt(data.top)
                if (data.left)
                    updateInfo.left = parseInt(data.left)
                if (data.width)
                    updateInfo.width = parseInt(data.width)
                if (data.height)
                    updateInfo.height = parseInt(data.height)
                if (data.state)
                    updateInfo.state = data.state

                chrome.windows.update(wind.id, updateInfo, function (window) {
                    socket.emit('cmd_out', data);
                });
            });
            break;

        case "get_errors":
            data.retVal = pageErrors;
            socket.emit('cmd_out', data);
            console.log('--' + data.cmd + ' done:', data);
            break;

        case "clear_errors":
            pageErrors = [];
            socket.emit('cmd_out', data);
            console.log('--' + data.cmd + ' done:', data);
            break;

        case "pause":
            handlePause(socket, data);
            break;

        default:
            // runs all other actions in the current window & tab
            findActiveTabAndRunAction(socket, data);
    }
}

function handlePause(socket, data) {
    setExtensionIcon(true);
    chrome.browserAction.onClicked.addListener(function (tab) {
        socket.emit('cmd_out', data);
        setExtensionIcon();
    });
}

function findActiveTabAndRunAction(socket, data) {
    chrome.windows.getCurrent({}, function (window) {
        try {
            chrome.tabs.query({ active: true }, function (tabs) {
                tab = tabs[0]; // only work with the active tab - and there is only one active tab!             
                runActionInActivePage(socket, tab, data);
            });
        }
        catch (err) {
            console.log('-- ERROR: ' + err.message);
            data.error_code = 500;
            data.error_message = err.message;
            socket.emit('cmd_out', data);
        }
    });
}

function runActionInActivePage(socket, tab, data) {
    if (tab === undefined) {
        console.log('--' + data.cmd + ' error');
        data.error_code = 501;
        data.error_message = 'ERROR: Unable to find the active tab';
        socket.emit('cmd_out', data);
        return;
    }

    switch (data.cmd) {
        case "get_url":
            data.retVal = tab.url;
            socket.emit('cmd_out', data);
            console.log('--' + data.cmd + ' done');
            break;

        case "set_url":
            function tabUpdatedListener(tabId, changeInfo, tab) {
                console.log('--status=' + changeInfo.status + ' url=' + tab.url);
                if (changeInfo.status == 'complete' && tab.url !== 'about:blank') { /* timing issue where about:blank will be 'complete' before socket connection occurs before the about:blank tab is created*/
                    chrome.tabs.onUpdated.removeListener(tabUpdatedListener);
                    socket.emit('cmd_out', data);
                    console.log('--' + data.cmd + ' done');
                }
            }

            chrome.tabs.onUpdated.addListener(tabUpdatedListener);

            // updates the url - response will be sent after the page load is complete - see above
            chrome.tabs.update(tab.id, { url: data.value });
            break;

        case "screenshot":
            chrome.tabs.captureVisibleTab(tab.windowId, { format: "jpeg", quality: 70 }, function (dataUrl) {
                data.retVal = dataUrl;
                socket.emit('cmd_out', data);
                console.log('--' + data.cmd + ' done');
            });
            break;

        case "enable_network_stats":
            parseIncomingNetworkMessage();
            socket.emit('cmd_out', data);
            break;

        case "get_network_stats_latest_chrome_timestamp":
        case "get_network_stats":
            let networkStatsArray = Array.from(networkRequests.values());
            switch (data.cmd) {
                case "get_network_stats_latest_chrome_timestamp":
                    const latestChromeTimeStamp = networkStatsArray.reduce((last, current) => current.startTime > last ? current.startTime : last, 0);
                    data.retVal = latestChromeTimeStamp;
                    break;

                case "get_network_stats":
                    if (data.path) {
                        // lowerbound value specified in the path, for instance: http://restbot/955664.555762?get_network_stats instead of http://restbot/?get_network_stats
                        const lowerBoundChromeTimeStamp = parseFloat(data.path);
                        networkStatsArray = networkStatsArray.filter(current => current.startTime > lowerBoundChromeTimeStamp);
                    }

                    const sortedNetworkStats = networkStatsArray.sort((a, b) => {
                        if (a.startTime > b.startTime) {
                            return 1;
                        }
                        if (a.startTime < b.startTime) {
                            return -1;
                        }
                        return 0;
                    });
                    data.retVal = sortedNetworkStats;
                    break;
            }

            socket.emit('cmd_out', data);
            break;

        case "fullpage_screenshot":
            var tabId = tab.id;
            var debuggeeId = { tabId: tabId };
{'fraction_non_alphanumeric': 0.11431033608759568, 'fraction_numerical': 0.005271962285192883, 'mean_word_length': 1.3852013057671382, 'pattern_counts': {'":': 32, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '751969', 'n_tokens_mistral': 5281, 'n_tokens_neox': 4959, 'n_words': 1075}