1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
/* global chrome */
export enum MsgType {
updatePatterns = "updatePatterns",
getPatterns = "getPatterns",
updateCalendars = "updateCalendars",
getCalendars = "getCalendars",
getCalEvents = "getCalEvents",
updateConfig = "updateConfig",
getConfig = "getConfig",
getGraphData = "getGraphData",
clearCache = "clearCache",
fetchCalendars = "fetchCalendars",
fetchColors = "fetchColors",
login = "login",
logout = "logout",
getLoggedIn = "getLoggedIn"
}
function stringifyMsgType(opt: MsgType): string { return MsgType[opt]; }
function parseMsgType(s: string): MsgType {
switch (s) {
case "updatePatterns": return MsgType.updatePatterns;
case "getPatterns": return MsgType.getPatterns;
case "updateCalendars" : return MsgType.updateCalendars;
case "getCalendars": return MsgType.getCalendars;
case "getCalEvents": return MsgType.getCalEvents;
case "updateConfig": return MsgType.updateConfig;
case "getConfig": return MsgType.getConfig;
case "getGraphData": return MsgType.getGraphData;
case "clearCache": return MsgType.clearCache;
case "fetchCalendars": return MsgType.fetchCalendars;
case "fetchColors": return MsgType.fetchColors;
case "login": return MsgType.login;
case "logout": return MsgType.logout;
case "getLoggedIn": return MsgType.getLoggedIn;
default: console.error(`unknown MsgType: ${s}`);
}
}
export class Msg<T> {
id: number;
opt: MsgType;
data: T;
constructor(id: number, opt: MsgType, data: T) {
this.id = id;
this.opt = opt;
this.data = data;
}
genResp(data: T) { return new Msg(this.id, this.opt, data); }
deflate() {
return {
id: this.id,
opt: stringifyMsgType(this.opt),
data: this.data
}
}
static inflate = <T>(obj: {id: number, opt: MsgType, data: T}) => (
new Msg(obj.id, parseMsgType(obj.opt), obj.data)
);
}
export class MsgClient {
requestCallback: {
ids: number[],
inFlight: {[id: number]: (msg: Msg<any>) => void; },
maxId: number
};
port: chrome.runtime.Port;
constructor(channelName: string) {
let port = chrome.runtime.connect({name: channelName});
this.requestCallback = {inFlight: {}, ids: [], maxId: 0};
const rcb = this.requestCallback;
port.onMessage.addListener((msg) => {
console.log(msg);
let cb = rcb.inFlight[msg.id];
console.assert(cb !== undefined);
rcb.ids.push(msg.id);
cb(msg);
});
this.port = port;
}
sendMsg({ opt, data }: { opt: MsgType, data: any }): Promise<Msg<any>> {
const rcb = this.requestCallback;
let cb;
let pm = new Promise<Msg<any>>(resolve => { cb = resolve; });
let id;
if (rcb.ids.length > 0) {
id = rcb.ids.pop();
} else {
id = rcb.maxId++;
}
rcb.inFlight[id] = cb;
this.port.postMessage((new Msg(id, opt, data)).deflate());
return pm;
}
}
|