0

I have an event for paste in a BrowserAction and I need to send either the Event object or its clipboardData.items property to a Background Script.

I've tried extracting the contents, but it doesn't retain the properties / methods.

Any normal object works, but Event objects do not retain their values.

I've also tried deep copies using Object.assign, but the contents are never passed to the Background script when using chrome.runtime.sendMessage().

Really appreciate the help as all my work goes to the trash if I can't get this to work.

My goal is to read an image file from the clipboard and then upload it to a website. Here's the relevant code to the problem I have:

const body = document.querySelector('body');

body.addEventListener('paste', (event) => {
  const item = [...event.clipboardData.items].pop();
  const message = {
    fn: 'pasteEvent',
    text: item
  }
  chrome.runtime.sendMessage(message);
});
user2046
  • 151
  • 1
  • 3
  • No, DOM events aren't JSON-compatible so you can't send them. Either read the items data and encode it into a string (or a blob object URL) or use the new asynchronous Clipboard API. Your extension will probably need `"clipboardRead"` permission in manifest.json. – wOxxOm Nov 02 '19 at 19:10
  • @wOxxOm Thanks for the help, but I have no idea how to go about that. My goal is to read an image from the clipboard and then upload it to a website. I would use Clipboard API but, according to the MDN docs, Firefox doesn't support the `read` method (it treats it as `readText`). – user2046 Nov 02 '19 at 20:12
  • Uhm, the first method I suggested was to read the image any way you can in the popup, then send the encoded data as a string into the background script. – wOxxOm Nov 03 '19 at 04:24
  • How do I go about encoding the data into a string? I've never done that before and I sure as heck don't know what methods I would use to go about that. – user2046 Nov 03 '19 at 04:43
  • I don't know either at the moment so let me [google it up](https://www.google.com/search?q=javascript+get+image+data+from+clipboard) and find something like [this](/a/51586232). I don't know if it'll work for you so keep looking. – wOxxOm Nov 03 '19 at 06:17

1 Answers1

0

Okay, I figured it out: you can't pass anything through runtime.sendMessage that can't be serialized.

So, the workaround I used was to create a DOMString Object URL that represents the file, pass it through sendMessage, then download it on the other end. I'm not sure if this was the best way, but it worked.

Step 1: Get the clipboard item as a file:

const item = [...event.clipboardData.items].pop();
const blob = item.getAsFile();

Step 2: Convert it to an Object URL:

const objUrl = URL.createObjectURL(blob);

Step 3: After you append it to your message and send it, you have to download the file and specify a response type of blob. I used Axios, but you can use whatever:

async function getFile(objUrl) {
  const config = {
    responseType: 'blob'
  };
  const res = await axios.get(objUrl, config);
  return res.data;
}
user2046
  • 151
  • 1
  • 3