Offscreen + Messaging API issue

Hello, I am trying to create an offscreen document for copying text to clipboard. I am trying to follow some of the examples I found in this issue: https://github.com/PlasmoHQ/plasmo/issues/527. In my background.ts file, I am trying to send a message to my offscreen.ts file like this:
const resp = await sendToBackground({
name: "offscreen",
body: {
alias
}
})
const resp = await sendToBackground({
name: "offscreen",
body: {
alias
}
})
this is the offscreen.ts file:
import OFFSCREEN_DOCUMENT_PATH from "url:~src/offscreen.html"

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.CLIPBOARD],
justification: "Writing text to clipboard"
})
}

const textEl: HTMLTextAreaElement = document.querySelector("#text")!
textEl.value = req.body.alias
textEl.select()
document.execCommand("copy")

res.send(true)
}

export default handler
import OFFSCREEN_DOCUMENT_PATH from "url:~src/offscreen.html"

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.CLIPBOARD],
justification: "Writing text to clipboard"
})
}

const textEl: HTMLTextAreaElement = document.querySelector("#text")!
textEl.value = req.body.alias
textEl.select()
document.execCommand("copy")

res.send(true)
}

export default handler
Heres my offscreen.html:
<!DOCTYPE html>
<html>

<head>
<title>Offscreen</title>
</head>

<body>
<script src="offscreen.ts" type="module"></script>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
<title>Offscreen</title>
</head>

<body>
<script src="offscreen.ts" type="module"></script>
</body>

</html>
But, when I try this, I get this error: Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist. Which I'm guessing means it can't find the message handler. Am I supposed to put the message handler in a different place or create the offscreen document in a different file? I would really appreciate if someone could help me fix this.
14 Replies
lab
labā€¢2y ago
You got it reversed - the sendToBackground should be in your offscreen.tsx, wheras the messaging handler should be in a /background/messaging/some-function.ts file
jonah
jonahOPā€¢2y ago
I moved the message handler to src/background/messages/clipboard.ts:
import OFFSCREEN_DOCUMENT_PATH from "url:~src/offscreen.html"

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.CLIPBOARD],
justification: "Writing text to clipboard"
})
}

const textEl: HTMLTextAreaElement = document.querySelector("#text")!
textEl.value = req.body.alias
textEl.select()
document.execCommand("copy")

res.send(true)
}

export default handler
import OFFSCREEN_DOCUMENT_PATH from "url:~src/offscreen.html"

import type { PlasmoMessaging } from "@plasmohq/messaging"

const handler: PlasmoMessaging.MessageHandler = async (req, res) => {
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.CLIPBOARD],
justification: "Writing text to clipboard"
})
}

const textEl: HTMLTextAreaElement = document.querySelector("#text")!
textEl.value = req.body.alias
textEl.select()
document.execCommand("copy")

res.send(true)
}

export default handler
But I am still receiving the same error when I try to run this in is my background.ts. file.
const resp = await sendToBackground({
name: "clipboard",
body: {
alias
}
})
const resp = await sendToBackground({
name: "clipboard",
body: {
alias
}
})
Is it possible that its not working because I'm running sendToBackground in an event listener for a context menu? I am still a bit confused on the point of an offscreen.ts / offscreen.tsx file, what exactly should I put in it and how should I access it from a context menu?
lab
labā€¢2y ago
that function is meant to be run outside of bgsw
jonah
jonahOPā€¢2y ago
šŸ¤¦ā€ā™‚ļø that makes a lot of sense. Because I'm running the code in an event listener in the bsgw, I changed my code to this (sort of following the example google gave):
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.CLIPBOARD],
justification: "Writing text to clipboard"
})
}

chrome.runtime.sendMessage({
type: "copy-data-to-clipboard",
target: "offscreen-doc",
data: alias.address
})
if (!(await chrome.offscreen.hasDocument())) {
await chrome.offscreen.createDocument({
url: OFFSCREEN_DOCUMENT_PATH,
reasons: [chrome.offscreen.Reason.CLIPBOARD],
justification: "Writing text to clipboard"
})
}

chrome.runtime.sendMessage({
type: "copy-data-to-clipboard",
target: "offscreen-doc",
data: alias.address
})
and then added this to my offscreen.ts
chrome.runtime.onMessage.addListener(handleMessages)

async function handleMessages(message: any) {
console.log(message)
// Return early if this message isn't meant for the offscreen document.
if (message.target !== "offscreen-doc") {
return
}

// Dispatch the message to an appropriate handler.
switch (message.type) {
case "copy-data-to-clipboard":
handleClipboardWrite(message.data)
break
default:
console.warn(`Unexpected message type received: '${message.type}'.`)
}
}

const textEl = document.querySelector("#text")! as HTMLTextAreaElement

async function handleClipboardWrite(data: string) {
try {
// `document.execCommand('copy')` works against the user's selection in a web
// page. As such, we must insert the string we want to copy to the web page
// and to select that content in the page before calling `execCommand()`.
textEl.value = data
textEl.select()
document.execCommand("copy")
} finally {
// Job's done! Close the offscreen document.
window.close()
}
}
chrome.runtime.onMessage.addListener(handleMessages)

async function handleMessages(message: any) {
console.log(message)
// Return early if this message isn't meant for the offscreen document.
if (message.target !== "offscreen-doc") {
return
}

// Dispatch the message to an appropriate handler.
switch (message.type) {
case "copy-data-to-clipboard":
handleClipboardWrite(message.data)
break
default:
console.warn(`Unexpected message type received: '${message.type}'.`)
}
}

const textEl = document.querySelector("#text")! as HTMLTextAreaElement

async function handleClipboardWrite(data: string) {
try {
// `document.execCommand('copy')` works against the user's selection in a web
// page. As such, we must insert the string we want to copy to the web page
// and to select that content in the page before calling `execCommand()`.
textEl.value = data
textEl.select()
document.execCommand("copy")
} finally {
// Job's done! Close the offscreen document.
window.close()
}
}
But, I don't think the message is getting to the offscreen.ts file. Should I be sending messages in a different way?
lab
labā€¢2y ago
this won't wokr btw bc BGSW does NOT have document to grab clipboard data, the easiest way to do so is via a CS, then you can pipe that data to the main world CS and invoke exec "copy" I'm not sure if isolated CS can exec copy :d but main world def can
jonah
jonahOPā€¢2y ago
you know what im just gonna wait for the clipboard api to be added in service workers
jonah
jonahOPā€¢2y ago
they have this in their repo so hopefully its gonna come out soon
No description
lab
labā€¢2y ago
interesting I'm not sure if they would ever add it TBH xd... they tried to trim it down so that ppl would open an explicit page instead of an offscreen one
jonah
jonahOPā€¢2y ago
today: - I learned the shopify checkout ui extensions are missing support for something that existed in a legacy api and is coming soon - I learned that there is going to be a clipboard api added eventually to extension service workers šŸ˜­ woah they even have bullet point support now this is also cool
lab
labā€¢2y ago
lol oh nice full markdown?
jonah
jonahOPā€¢2y ago
almost they dont support (https://asdasd.com)[text] or is it i always forget the order i dont think they should support it bc so many people will be clicking bad things
lab
labā€¢2y ago
lol yeah they already click without thinking already
jonah
jonahOPā€¢2y ago
true
Arcane
Arcaneā€¢2y ago
@j0ner has reached level 4. GG!
Want results from more Discord servers?
Add your server