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
101
102
103
104
105
106
107
108
109
110
|
const PROTOCOL_VERSION = 0
const port = browser.runtime.connectNative("hidit")
port.onDisconnect.addListener(port => {
if (port.error) {
// TODO(V): Write a more precise error message
console.error(`Disconnected due to an error: ${port.error.message}`)
// TODO(V): Do we want to restart the application here? Do we want to kill the extension?
}
})
function checkVersion(version) {
if (version !== PROTOCOL_VERSION) {
console.error(`Native application protocol has an incompatible version! Wanted ${PROTOCOL_VERSION}, got ${version}`)
// TODO(V): Fatal error. Ideally we would repeat this process once a second or so, and display
// an error icon in the toolbar to alert the user, along with some information on how to solve it.
}
port.onMessage.removeListener(checkVersion)
port.onMessage.addListener(([command, args]) => {
switch (command) {
case "console:log": console.log(...args); break
case "console:error": console.error(...args); break
default: throw new Error(`Unknown command ${command}`)
}
})
browser.windows.onCreated.addListener(window => {
port.postMessage(["window:create", window])
})
browser.windows.onFocusChanged.addListener(windowId => {
port.postMessage(["window:focus", windowId])
})
browser.windows.onRemoved.addListener(windowId => {
port.postMessage(["window:destroy", windowId])
})
browser.windows.getAll().then(windows => {
port.postMessage(["init:windows", windows])
})
browser.tabs.onActivated.addListener(({ windowId, tabId, previousTabId }) => {
port.postMessage(["tab:activate", [windowId, tabId, previousTabId]])
})
browser.tabs.onAttached.addListener((tabId, { newWindowId, newPosition }) => {
port.postMessage(["tab:attach", [tabId, newWindowId, newPosition]])
})
browser.tabs.onCreated.addListener(tab => {
port.postMessage(["tab:create", tab])
})
browser.tabs.onDetached.addListener((tabId, { oldWindowId, oldPosition }) => {
port.postMessage(["tab:detach", [tabId, oldWindowId, oldPosition]])
})
browser.tabs.onHighlighted.addListener(({ windowId, tabIds }) => {
port.postMessage(["tab:select", [windowId, tabIds]])
})
browser.tabs.onMoved.addListener((tabId, info) => {
port.postMessage(["tab:move", [tabId, info]])
})
browser.tabs.onRemoved.addListener((tabId, { windowId, isWindowClosing }) => {
port.postMessage(["tab:destroy", [tabId, windowID, isWindowClosing]])
})
// Note: MDN has the following to say:
// "This event may not be relevant for or supported by browsers other than Chrome."
browser.tabs.onReplaced.addListener((newTabId, oldTabId) => {
port.postMessage(["tab:replace", [oldTabId, newTabId]])
})
// TODO(V): Remove the tab parameter, it shouldn't be necessary if we're doing deltas properly
browser.tabs.onUpdated.addListener((tabId, info, tab) => {
port.postMessage(["tab:update", [tabId, info, tab]])
})
browser.tabs.onZoomChange.addListener(info => {
port.postMessage(["tab:zoom", info])
})
browser.tabs.query({}).then(tabs => {
port.postMessage(["init:tabs", tabs])
})
browser.contextualIdentities.onCreated.addListener(({ contextualIdentity }) => {
port.postMessage(["context:create", contextualIdentity])
})
browser.contextualIdentities.onRemoved.addListener(({ contextualIdentity }) => {
port.postMessage(["context:destroy", contextualIdentity])
})
browser.contextualIdentities.onUpdated.addListener(({ contextualIdentity }) => {
port.postMessage(["context:update", contextualIdentity])
})
browser.contextualIdentities.query({}).then(contexts => {
port.postMessage(["init:contexts", contexts])
// TODO(V): either send over the files in resource://usercontext-content/ or vendor them
})
}
port.onMessage.addListener(checkVersion)
port.postMessage(PROTOCOL_VERSION)
|