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)