What is the best way to add attachments to the clipboard in a Chrome extension?

One possible way to achieve this is by using the navigator.clipboard.write API, but keep in mind that this API is not available to background pages of Chrome extensions. A method I attempted involved creating a blob like this:

    let blobFinal = null; // will store the blob object
    const img = document.createElement('img');
    // insert image data
    img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAsCAYAAAANUxr1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAfJSURBVFhH7ZhLbFTXHcZ/9955j+dhjz1+Y/MqUEckgFwaQC0EuXmoUdNIjUiiSo2qZtFFd1GzaZR02U0X3VRZt1K6SKUWVVGloLJAFiFxEAGBwTZg/Lbn/bpzZ+6j/zsel6QteIwEYsE3ur7nPs453/nO/3WtjLz6rsNjBLV5fmzwhNBmeEJoMzwhtBm05L5j7zfbW8LR/dt5762XeOHZETRV4Vu...
    document.body.appendChild(img);
    setTimeout(() => {
      // create canvas of similar size
      const canvas = document.createElement('canvas');
      canvas.width = img.clientWidth;
      canvas.height = img.clientHeight;
      const context = canvas.getContext('2d');
      // copy image onto it
      context.drawImage(img, 0, 0);
      // we can apply transformations here if needed
      // convert canvas data into a blob (asynchronous)
      canvas.toBlob(function(blob) {
        blobFinal = blob;
        console.log('blob', blob);
        document.body.removeChild(img);
      }, 'image/png');
    }, 1000);

Next step involves attaching this blob to clipboard during a '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, upon pasting this data, no files show up 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);
      }
    });

Even if there was one file, its 'size' property would still be zero. Surprisingly, information regarding this issue seems scarce. Therefore, my question remains: how can files be attached to the clipboard within a Chrome extension?

Answer №1

This example demonstrates the following steps:

  1. A service worker stores the value "hoge" in storage.
  2. The service worker opens clipboard.html.
  3. clipboard.html calls clipboard.js.
  4. clipboard.js retrieves the value "hoge" from storage and writes it to the clipboard.
  5. clipboard.js closes clipboard.html.

Please note:
The documentation for Clipboard.writeText() states the following:

The "clipboard-write" permission is automatically granted through the Permissions API to pages when they are active in the current 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);
    });
  });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Choosing between cjs and esm for a React components library

I'm working on a components library that will soon be published to npm for use in a razzle app. My main query revolves around the best practices for building these packages - should they be built with CommonJS (cjs) or ECMAScript Modules (esm)? And wh ...

A tutorial on submitting multipart/form-data using JavaScript

I am currently facing an issue with the uploadImage API in my frontend. I am using input[type='file'] to obtain image data from users and then POSTing it to my API. In the backend, I am parsing this data using formidable. However, the problem ari ...

Moving Cursor Automatically to the End Upon Rejecting Input

I have a form input where users can enter values. I need to validate the inputs to ensure they only contain numbers, dots, and commas. If the input is invalid, I want to prevent it from being stored in the input field. To achieve this, I have implemented ...

Progressive rendering of a substantial mesh using three.js

How can I efficiently render a large static mesh in three.js, even if it's 2 GB with tens of millions of polygons? My plan is to stream the mesh geometry buffers into indexedDB and render them progressively to the screen, all while maintaining an int ...

How can I alter the background color while performing a transformation in JS/CSS?

I'm currently working on achieving a flipboard effect for some divs, where one side is white and the other is black. Here's what I have so far: setInterval(function () { document.getElementById('test').classList.toggle('flipped& ...

Having trouble accessing properties of an undefined object when trying to read 'credentials' in Firebase Auth within ReactJS

I need to verify the user's password again before allowing them to change it. Currently, my Firebase Auth setup is defined in Firebase.js and exported correctly //appConfig = ...(all the configurations here) const app = firebase.initializeApp(appConf ...

Issue with Nodemailer OAuth2 2LO authentication when deployed on Heroku

const { EMAIL_FROM, EMAILS_TO, USER, GMAIL_CLIENT_ID, GMAIL_PRIVATE_KEY } = process.env; let transporter = nodemailer.createTransport({ host: 'smtp.gmail.com', port: 465, secure: true, auth: { type: &a ...

Siblings are equipped with the advanced selector feature to

I'm struggling to understand this setup I have: <div class="container"> for n = 0 to ... <a href="some url">Link n</a> endfor for each link in ".container" <div class="poptip"></div> ...

a callback may seem like it's not a function, but in reality, it is

This question might seem simple, but I'm struggling to grasp the concept of callbacks, especially in NodeJS. My issue arises when trying to retrieve data from MySQL, something that is usually straightforward in most programming languages: In my rout ...

Increase the worth of current value

Whenever a user enters their name into an input box, I want it to be shown after the word 'hello'. However, currently, the word 'hello' gets replaced by the user's name instead of being displayed after it. var name = document.ge ...

Using conditional logic to check if a column cell is empty

I need help writing a Javascript function that will loop through rows in a table and only change the background color of cells in "column2" if they are empty. My current code is not working as expected, as it colors all rows instead of just those with empt ...

Combining AngularJS objects from dual HTTP requests

My goal is to combine two HTTP.get requests into one $scope in order to display the data in the same ng-repeat table. I am utilizing chained promises in my AngularJS application as shown below: AngularJS: function getContainer() { $http.get(" ...

Exploring React hook functionalities can lead to discovering unexpected issues such as cyclic dependencies on location.hash when

My implementation of a useEffect involves reading the location.hash and adjusting the hash based on certain dependencies. Here is a snippet of how it works: useEffect(() => { const hashAlreadyPresent = () => { const hashArr = history.locati ...

Reassemble the separated string while skipping over every other element in the array created by splitting it

Currently, I am working on the following URL: demo.example.in/posts/0ewsd/13213 My goal is to extract the hostname (demo.example.in) and the path (posts/0ewsd/13213) from this URL. urlHost = 'demo.example.in/posts/0ewsd/13213'; let urlHostName ...

Is it possible to locate an element using regex in Python while using Selenium?

Is it possible to interact with a dynamically generated dropdown list using Selenium if I only know the phrase present in its id or class name? Can Selenium locate an element using regex and click on it accordingly? ...

Looking for a way to store data in local storage so it remains even after the page is reloaded? I tried adding a local storage function, but it doesn't appear to be

I am currently working on a project involving a work day scheduler and I am facing challenges in saving data within the schedule events, like at 8am, and making sure it persists on reload. The colored time block element that changes as hours pass in the da ...

.fetchevery(...).then has no function

I recently upgraded Angular to version 1.6.4. As a result, I made changes to the code by replacing .success and .error with .then However, now I am encountering the following error: An unexpected TypeError occurred: .getAll(...).then is not a function ...

Quoting Properties in Javascript Objects

If we have the object below: var ObjectName = { propertyOne: 1, propertyTwo: 2 } Do we need to include quotes around the object properties like this? var ObjectName = { 'propertyOne': 1, 'propertyTwo': 2 } Is the sol ...

Replace the function if it is specified in the object, otherwise use the default functionality

Having a calendar widget written in TypeScript, I am able to bind a listener to a separate function. However, I desire this separate function to have default functionality until someone overrides it in the config object passed to the constructor. Within th ...

Utilizing dropbox.js in combination with OAuth 1: A step-by-step guide

I'm in the process of revamping a website that already exists, and although I have the code from the previous version, I'm encountering challenges replicating certain functionalities in the new iteration. Here's the situation: The user is ...