From 18b619e164ced91cf0ac8d3fd3c18be1f07df1cc Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 18 Feb 2016 12:29:35 +0100 Subject: move mitmproxy/web to root --- web/src/js/store/store.js | 181 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 web/src/js/store/store.js (limited to 'web/src/js/store/store.js') diff --git a/web/src/js/store/store.js b/web/src/js/store/store.js new file mode 100644 index 00000000..5024049f --- /dev/null +++ b/web/src/js/store/store.js @@ -0,0 +1,181 @@ + +var _ = require("lodash"); +var $ = require("jquery"); +var EventEmitter = require('events').EventEmitter; + +var utils = require("../utils.js"); +var actions = require("../actions.js"); +var dispatcher = require("../dispatcher.js"); + + +function ListStore() { + EventEmitter.call(this); + this.reset(); +} +_.extend(ListStore.prototype, EventEmitter.prototype, { + add: function (elem) { + if (elem.id in this._pos_map) { + return; + } + this._pos_map[elem.id] = this.list.length; + this.list.push(elem); + this.emit("add", elem); + }, + update: function (elem) { + if (!(elem.id in this._pos_map)) { + return; + } + this.list[this._pos_map[elem.id]] = elem; + this.emit("update", elem); + }, + remove: function (elem_id) { + if (!(elem_id in this._pos_map)) { + return; + } + this.list.splice(this._pos_map[elem_id], 1); + this._build_map(); + this.emit("remove", elem_id); + }, + reset: function (elems) { + this.list = elems || []; + this._build_map(); + this.emit("recalculate"); + }, + _build_map: function () { + this._pos_map = {}; + for (var i = 0; i < this.list.length; i++) { + var elem = this.list[i]; + this._pos_map[elem.id] = i; + } + }, + get: function (elem_id) { + return this.list[this._pos_map[elem_id]]; + }, + index: function (elem_id) { + return this._pos_map[elem_id]; + } +}); + + +function DictStore() { + EventEmitter.call(this); + this.reset(); +} +_.extend(DictStore.prototype, EventEmitter.prototype, { + update: function (dict) { + _.merge(this.dict, dict); + this.emit("recalculate"); + }, + reset: function (dict) { + this.dict = dict || {}; + this.emit("recalculate"); + } +}); + +function LiveStoreMixin(type) { + this.type = type; + + this._updates_before_fetch = undefined; + this._fetchxhr = false; + + this.handle = this.handle.bind(this); + dispatcher.AppDispatcher.register(this.handle); + + // Avoid double-fetch on startup. + if (!(window.ws && window.ws.readyState === WebSocket.CONNECTING)) { + this.fetch(); + } +} +_.extend(LiveStoreMixin.prototype, { + handle: function (event) { + if (event.type === actions.ActionTypes.CONNECTION_OPEN) { + return this.fetch(); + } + if (event.type === this.type) { + if (event.cmd === actions.StoreCmds.RESET) { + this.fetch(event.data); + } else if (this._updates_before_fetch) { + console.log("defer update", event); + this._updates_before_fetch.push(event); + } else { + this[event.cmd](event.data); + } + } + }, + close: function () { + dispatcher.AppDispatcher.unregister(this.handle); + }, + fetch: function (data) { + console.log("fetch " + this.type); + if (this._fetchxhr) { + this._fetchxhr.abort(); + } + this._updates_before_fetch = []; // (JS: empty array is true) + if (data) { + this.handle_fetch(data); + } else { + this._fetchxhr = $.getJSON("/" + this.type) + .done(function (message) { + this.handle_fetch(message.data); + }.bind(this)) + .fail(function () { + EventLogActions.add_event("Could not fetch " + this.type); + }.bind(this)); + } + }, + handle_fetch: function (data) { + this._fetchxhr = false; + console.log(this.type + " fetched.", this._updates_before_fetch); + this.reset(data); + var updates = this._updates_before_fetch; + this._updates_before_fetch = false; + for (var i = 0; i < updates.length; i++) { + this.handle(updates[i]); + } + }, +}); + +function LiveListStore(type) { + ListStore.call(this); + LiveStoreMixin.call(this, type); +} +_.extend(LiveListStore.prototype, ListStore.prototype, LiveStoreMixin.prototype); + +function LiveDictStore(type) { + DictStore.call(this); + LiveStoreMixin.call(this, type); +} +_.extend(LiveDictStore.prototype, DictStore.prototype, LiveStoreMixin.prototype); + + +function FlowStore() { + return new LiveListStore(actions.ActionTypes.FLOW_STORE); +} + +function SettingsStore() { + return new LiveDictStore(actions.ActionTypes.SETTINGS_STORE); +} + +function EventLogStore() { + LiveListStore.call(this, actions.ActionTypes.EVENT_STORE); +} +_.extend(EventLogStore.prototype, LiveListStore.prototype, { + fetch: function(){ + LiveListStore.prototype.fetch.apply(this, arguments); + + // Make sure to display updates even if fetching all events failed. + // This way, we can send "fetch failed" log messages to the log. + if(this._fetchxhr){ + this._fetchxhr.fail(function(){ + this.handle_fetch(null); + }.bind(this)); + } + } +}); + + +module.exports = { + EventLogStore: EventLogStore, + SettingsStore: SettingsStore, + FlowStore: FlowStore +}; \ No newline at end of file -- cgit v1.2.3