Skip to content

Instantly share code, notes, and snippets.

@beccasaurus
Created November 21, 2018 00:59
Show Gist options
  • Save beccasaurus/3937bee8e56f1ff88d8574b7fe2d97e8 to your computer and use it in GitHub Desktop.
Save beccasaurus/3937bee8e56f1ff88d8574b7fe2d97e8 to your computer and use it in GitHub Desktop.
Chrome Extension Long-Running Messaging WIP
// I could use a class and whatnot.
// Maybe later.
// Just making it work.
//
// Interface: sendMessage({ message }, (response) => {})
// listenForMessages((message, sendResponse) => {})
//
var __messagingPort__ = null
const __messagingPortName__ = "OkCupidExtension"
const __messagingCallbacks__ = new Map()
const __messagingInContentScript__ = () => location.protocol != "chrome-extension:"
const __messagingCreateAckId__ = () => Math.random().toString(36)
const __messagingCreateReplyFn__ = (ackId) => {
return (message) => {
__messagingWithPort__((port) => {
const outerMessage = { ackId: ackId, innerMessage: message }
port.postMessage(outerMessage)
})
}
}
const __messagingWithPort__ = (portReady) => {
if (__messagingPort__ == null) {
if (__messagingInContentScript__()) {
console.log("[messaging] Initializing Port to chrome.runtime")
__messagingPort__ = chrome.runtime.connect({ name: __messagingPortName__ });
__messagingPort__.onDisconnect.addListener(() => {
console.log("Port was disconnected?")
console.log("Last error", chrome.runtime.lastError)
})
portReady(__messagingPort__)
} else {
// get the currently active tab to send messages to (where content script is running)
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
const tabId = tabs[0].id
console.log("[messaging] Initializing Port to chrome.tabs", tabId)
__messagingPort__ = chrome.tabs.connect(tabId, { name: __messagingPortName__ });
__messagingPort__.onDisconnect.addListener(() => {
console.log("Port was disconnected?")
console.log("Last error", chrome.runtime.lastError)
})
portReady(__messagingPort__)
});
}
} else {
console.log("[messaging] Port already initialized")
portReady(__messagingPort__)
}
}
function sendMessage(message, callback) {
__messagingWithPort__((port) => {
if (callback) {
const ackId = __messagingCreateAckId__()
const outerMessage = { ackId: ackId, innerMessage: message }
__messagingCallbacks__.set(ackId, callback)
console.log("[messaging] Sending Message", outerMessage)
port.postMessage(outerMessage)
} else {
// Regular message without an ackId/callback
console.log("[messaging] Sending Message", message)
port.postMessage(message)
}
})
}
function listenForMessages(handler) {
console.log("[messaging] Registering onMessage handler")
__messagingWithPort__((port) => {
port.onMessage.addListener((message) => {
console.log("[messaging] Received Message", message)
if (message.ackId && message.innerMessage) {
// This is a callback from one of our sent messages, invoke the known callback!
if (__messagingCallbacks__.has(message.ackId)) {
const callback = __messagingCallbacks__.get(message.ackId)
__messagingCallbacks__.delete(message.ackId)
callback(message.innerMessage)
// This is an unknown ackId, we're the actual receiver
// when we reply, we send the ackId so the sender can invoke their callback
} else {
const receivedMessage = message.innerMessage
const sendResponseFunction = __messagingCreateReplyFn__(message.ackId)
handler(receivedMessage, sendResponseFunction)
}
} else {
// Regular message without an ackId/callback
handler(message)
}
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment