Gaurang Tandon
Gaurang Tandon

Reputation: 6761

How to attach files to clipboard in Chrome extension?

The easiest way to do this would be to the navigator.clipboard.write API which is not available to the background pages of Chrome extensions. I have tried to create a blob like so:

    let blobFinal = null; // this will contain our blob object
    const img = document.createElement('img');
    // a train emoji
    img.src = 'data:image/png;base64,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';
    document.body.appendChild(img);
    setTimeout(() => {
      // make <canvas> of the same size
      const canvas = document.createElement('canvas');
      canvas.width = img.clientWidth;
      canvas.height = img.clientHeight;
      const context = canvas.getContext('2d');
      // copy image to it (this method allows to cut image)
      context.drawImage(img, 0, 0);
      // we can context.rotate(), and do many other things on canvas
      // toBlob is async operation, callback is called when done
      canvas.toBlob(function(blob) {
        blobFinal = blob;
        console.log('blob', blob);
        document.body.removeChild(img);
      }, 'image/png');
    }, 1000);

Then I attach this blob to the clipboard during its 'copy' event:

    editor.addEventListener('copy', (evt) => {
      // preserve text data
      evt.clipboardData.setData('text/plain', evt.clipboardData.getData('text/plain'));
      evt.clipboardData.setData('text/html', evt.clipboardData.getData('text/html'));
      // add binary data
      evt.clipboardData.setData('image/png', blobFinal);
      evt.preventDefault();
    });

However, when I paste this data, there are no files in the clipboard:

    editor.addEventListener('paste', (evt) => {
      console.log(evt.clipboardData.files.length); // prints 0
      for (const file of evt.clipboardData.files) {
        console.log('Size of file', file.size);
      }
    });

And, even if there is one file, its property size is zero. I am surprisingly not able to find any question on this topic. So, my question is, how to attach files to clipboard in a Chrome extension?

Upvotes: 1

Views: 211

Answers (1)

Norio Yamamoto
Norio Yamamoto

Reputation: 1792

This sample does the following:

  1. Service worker sets "hoge" to storage.
  2. Service worker opens clipboard.html.
  3. clipboard.html calls clipboard.js.
  4. clipboard.js gets "hoge" from storage and writes to clipboard.
  5. clipboard.js closes clipboard.html.

Note:
The documentation of Clipboard.writeText() has the following description:

The "clipboard-write" permission of the Permissions API is granted automatically to pages when they are in the active tab.

manifest.json

{
  "name": "clipboard",
  "version": "1.0",
  "manifest_version": 3,
  "permissions": [
    "storage"
  ],
  "background": {
    "service_worker": "background.js"
  }
}

background.js

chrome.storage.local.set({ key: "hoge" }, () => {
  chrome.tabs.create({
    url: "clipboard.html"
  });
});

clipboard.html

<!DOCTYPE html>
<html>

<body>
  <script src="clipboard.js"></script>
</body>

</html>

clipboard.js

chrome.storage.local.get("key", (result) => {
  navigator.clipboard.writeText(result["key"]).then(() => {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      chrome.tabs.remove(tabs[0].id);
    });
  });
});

Upvotes: 1

Related Questions