<commit_before>/*******************
 * Delegate Class
 *
 * The delegate is used for passing messages back and forth
 * between the client page and the extension background
 *
********************/

Delegate.prototype.DEBUG = true;

Delegate.prototype.options = {};
Delegate.prototype.currentLogins = {};

Delegate.prototype.options.configURL = "https://raw.github.com/waltzio/waltz/master/deploy/site_configs.json";
Delegate.prototype.options.backupConfigURL = chrome.extension.getURL("build/site_configs.json");

if (Delegate.prototype.DEBUG) {
    Delegate.prototype.options.configURL = Delegate.prototype.options.backupConfigURL;
    debug.enable('waltz:*');
}

function Delegate(opts) {
	var _this = this;

    this.options = $.extend(this.options, opts);

    this.storage = new Storage();
    this.analytics = new Analytics();
    this.crypto = new Crypto();
    this.log = debug('waltz:delegate.js');

    this.ongoingAJAXRequests = {};

    if (navigator.onLine) {
        start();
    } else {
        window.addEventListener('online', function() {
            window.removeEventListener('online');
            start();
        });
    }

    function start() {
        _this.storage.getOptions(function(options) {
            _this.init(options);
        });
    }
}

Delegate.prototype.init = function(options) {
    var _this = this;

    this.options = $.extend(this.options, options);
    this.storage.subscribe(this.storage.OPTIONS_KEY, function(changes) {
        _this.options = changes.newValue;
    });

    this.pubnub = PUBNUB.init({
        subscribe_key : '<KEY>'
    });

    //Add the context menu
    chrome.contextMenus.create({
        id: 'waltz-main',
        title: 'Waltz',
        onclick: function(info, tab) {
            chrome.tabs.create({url: "/html/options.html"});
        }
    });

    chrome.webRequest.onBeforeRequest.addListener(
        this.onBeforeAJAXRequest.bind(this),
        {
            urls: ["*://*/*"],
            types: ["xmlhttprequest"]
        }
    );

    chrome.webRequest.onCompleted.addListener(
        this.onAJAXCompleted.bind(this),
        {
            urls: ["*://*/*"],
            types: ["xmlhttprequest"]
        }
    );

    // Listens to requests, so we can redirect to the original page
    // after a successful login.
    chrome.webRequest.onCompleted.addListener(
        this.handleSuccessfulLogin.bind(this),
        {
            urls: Object.keys(this.currentLogins),
            types: ["main_frame"]
        }
    );

    chrome.webRequest.onCompleted.addListener(
        this.handleLinkCaptures.bind(this),
        {
            urls: ['https://*.getclef.com/*'],
            types: ["main_frame"]
        }
    );

    chrome.webRequest.onHeadersReceived.addListener(
        this.handleCSPHeader.bind(this),
        {
            urls: ["*://*/*"],
            types: ["main_frame"]
        },
        ["blocking", "responseHeaders"]
    );

	// load configs and fall back if cannot access Github
	this.configsLoaded = $.Deferred();

    $.ajax({
        url: this.options.configURL,
        dataType: 'json',
        success: this.updateSiteConfigs.bind(this),
        error:function() {
            $.ajax({
                url: _this.options.backupConfigURL,
                dataType: 'json',
                success: _this.updateSiteConfigs.bind(_this)
            });
        }
    });

    // bind the router
    chrome.runtime.onMessage.addListener(this.router.bind(this));

    // when the configs are done loading, blast off, baby!
    $.when(this.configsLoaded).then(this.syncAuthenticationState.bind(this));
};

Delegate.prototype.syncAuthenticationState = function (cb) {
    var _this = this;

    var n = 0;
    function run(callback) {
        _this.checkAuthentication(function(data) {
            if (data.error == "noconn") {
                _this.log('no connection, will retry in ' + Math.pow(2,n) + ' seconds.');
                // exponential backoff, hooray!
                setTimeout(run, Math.pow(2, n) * 1000);
                n = n + 1;
                return;
            }

            if (data.user) {
                _this.pubnubSubscribe(data);
                _this.loggedIn = true;
            } else {
                _this.loggedIn = false;
                _this.logout({ silent: true });
            }<commit_msg>rather than doing exponential backoff for authenticaton sync, try to sync every 1 second until we connect<commit_after>/*******************
 * Delegate Class
 *
 * The delegate is used for passing messages back and forth
 * between the client page and the extension background
 *
********************/

Delegate.prototype.DEBUG = true;

Delegate.prototype.options = {};
Delegate.prototype.currentLogins = {};

Delegate.prototype.options.configURL = "https://raw.github.com/waltzio/waltz/master/deploy/site_configs.json";
Delegate.prototype.options.backupConfigURL = chrome.extension.getURL("build/site_configs.json");

if (Delegate.prototype.DEBUG) {
    Delegate.prototype.options.configURL = Delegate.prototype.options.backupConfigURL;
    debug.enable('waltz:*');
}

function Delegate(opts) {
	var _this = this;

    this.options = $.extend(this.options, opts);

    this.storage = new Storage();
    this.analytics = new Analytics();
    this.crypto = new Crypto();
    this.log = debug('waltz:delegate.js');

    this.ongoingAJAXRequests = {};

    if (navigator.onLine) {
        start();
    } else {
        window.addEventListener('online', function() {
            window.removeEventListener('online');
            start();
        });
    }

    function start() {
        _this.storage.getOptions(function(options) {
            _this.init(options);
        });
    }
}

Delegate.prototype.init = function(options) {
    var _this = this;

    this.options = $.extend(this.options, options);
    this.storage.subscribe(this.storage.OPTIONS_KEY, function(changes) {
        _this.options = changes.newValue;
    });

    this.pubnub = PUBNUB.init({
        subscribe_key : '<KEY>'
    });

    //Add the context menu
    chrome.contextMenus.create({
        id: 'waltz-main',
        title: 'Waltz',
        onclick: function(info, tab) {
            chrome.tabs.create({url: "/html/options.html"});
        }
    });

    chrome.webRequest.onBeforeRequest.addListener(
        this.onBeforeAJAXRequest.bind(this),
        {
            urls: ["*://*/*"],
            types: ["xmlhttprequest"]
        }
    );

    chrome.webRequest.onCompleted.addListener(
        this.onAJAXCompleted.bind(this),
        {
            urls: ["*://*/*"],
            types: ["xmlhttprequest"]
        }
    );

    // Listens to requests, so we can redirect to the original page
    // after a successful login.
    chrome.webRequest.onCompleted.addListener(
        this.handleSuccessfulLogin.bind(this),
        {
            urls: Object.keys(this.currentLogins),
            types: ["main_frame"]
        }
    );

    chrome.webRequest.onCompleted.addListener(
        this.handleLinkCaptures.bind(this),
        {
            urls: ['https://*.getclef.com/*'],
            types: ["main_frame"]
        }
    );

    chrome.webRequest.onHeadersReceived.addListener(
        this.handleCSPHeader.bind(this),
        {
            urls: ["*://*/*"],
            types: ["main_frame"]
        },
        ["blocking", "responseHeaders"]
    );

	// load configs and fall back if cannot access Github
	this.configsLoaded = $.Deferred();

    $.ajax({
        url: this.options.configURL,
        dataType: 'json',
        success: this.updateSiteConfigs.bind(this),
        error:function() {
            $.ajax({
                url: _this.options.backupConfigURL,
                dataType: 'json',
                success: _this.updateSiteConfigs.bind(_this)
            });
        }
    });

    // bind the router
    chrome.runtime.onMessage.addListener(this.router.bind(this));

    // when the configs are done loading, blast off, baby!
    $.when(this.configsLoaded).then(this.syncAuthenticationState.bind(this));
};

Delegate.prototype.syncAuthenticationState = function (cb) {
    var _this = this;

    function run(callback) {
        _this.checkAuthentication(function(data) {
            if (data.error == "noconn") {
                _this.log('no connection, will retry in 1 seconds.');
                setTimeout(run, 1 * 1000);
                return;
            }

            if (data.user) {
                _this.pubnubSubscribe(data);
                _this.loggedIn = true;
            } else {
                _this.loggedIn = false;
                _this.logout({ silent: true });
            }
{'fraction_non_alphanumeric': 0.14214837890850351, 'fraction_numerical': 0.0017307026652821046, 'mean_word_length': 2.1349005424954792, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6323227', 'n_tokens_mistral': 2572, 'n_tokens_neox': 2460, 'n_words': 456}