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

Push the accordion tab upwards towards the top of the browser

I am working on an accordion menu that contains lengthy content. To improve user experience, I want to implement a slide effect when the accordion content is opened. Currently, when the first two menu items are opened, the content of the last item is disp ...

Having trouble passing an array from PHP to JavaScript

I'm facing an issue with the following code snippet: <?php $result = array(); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){ $result[] = sprintf("{lat: %s, lng: %s}",$row['lat'],$row['lng']);} ?> <?php $resultAM = joi ...

After upgrading to react native version 0.73, the user interface freezes and becomes unresponsive when working with react-native-maps

After upgrading my app to the newest version of react native 0.73.x, I encountered an issue where the UI on iOS starts freezing and becoming unresponsive in production. The main screen loads react-native-maps with numerous markers, and this was not a pro ...

Reset input fields upon jQuery removal

Currently, I am working on a form that includes a remove function. The function is functioning correctly, but I am facing an issue where I want the field values to be cleared when the remove function is triggered. This is necessary as I am sending input va ...

Encountering a React Runtime issue: The element type is invalid, expecting a string for built-in components or a class/function for composite components

Here is a glimpse of my code: import { React, useState, useEffect } from 'react'; import { GoogleMapReact } from 'google-map-react'; import styles from './Location.module.scss'; import pinstyles from './TheMap.module.scss ...

Traversing a hierarchical structure and building a REACT user interface based on it

Currently, I am tasked with a project that involves working with a hierarchy tree. The goal is to loop through the data provided by the tree and create a user-friendly UI representation of the hierarchy for seamless navigation. Here's an illustration ...

How do I automatically redirect to a different URL after verifying that the user has entered certain words using Javascript?

I want to create a function where if a user input on the "comments" id matches any word in my FilterWord's array, they will be redirected to one URL. If the input does not match, they will be redirected to another URL. The checking process should onl ...

Testing API route handlers function in Next.js with Jest

Here is a health check function that I am working with: export default function handler(req, res) { res.status(200).json({ message: "Hello from Next.js!" }); } Alongside this function, there is a test in place: import handler from "./heal ...

How can I create an input field that only reveals something when a specific code is entered?

I am currently developing a website using HTML, and I would like to create an admin section that requires a password input in order to access. After consulting resources on w3schools, I attempted the following code: <button onclick="checkPassword()" i ...

Endless repetition occurs when invoking a function within a v-for loop

I've encountered an issue while trying to populate an array using a method, leading to redundant data and the following warning message: You may have an infinite update loop in a component render function. Below is the code snippet in question: ...

Tips for customizing MUI PaperProps using styled components

I am trying to customize the width of the menu using styled components in MUI. Initially, I attempted the following: const StyledMenu = styled(Menu)` && { width: 100%; } `; However, this did not have any effect. After further research, I ...

Module Ionic not found

When I attempt to run the command "ionic info", an error is displayed: [ERROR] Error loading @ionic/react package.json: Error: Cannot find module '@ionic/react/package' Below is the output of my ionic info: C:\Users\MyPC>ionic i ...

Testing with karma/jasmine in AngularJS can lead to issues when there are conflicts between test

Currently experiencing challenges while running my midway tests (or integration tests, which are halfway between unit tests and E2E tests). Working with an AngularJS build featuring RequireJS, I am utilizing the RequireJS plugin in Karma to run the tests. ...

Exploring the capabilities of Vue.js, including the use of Vue.set()

Just starting out with Vuejs and I have a query regarding the correct approach to achieve what I want. My Objective I aim to have some dates stored in an array and be able to update them upon an event trigger. Initially, I attempted using Vue.set, which ...

Retrieve the information from the recently completed request

When the user inputs 'id' into the text field, I want to fetch a post based on the specific id entered by the user. If no id is provided, I would like to fetch the entire array of posts and then retrieve an id from the fetched data for testing pu ...

How to Convert Python Lists into JavaScript?

octopusList = {"first": ["red", "white"], "second": ["green", "blue", "red"], "third": ["green", "blue", "red"]} squidList = ["first", "second", "third"] for i in range(1): squid = random.choice(squidList) octopus = random. ...

Tips for creating a functional null option using the select ng-options feature

While there are a few questions and answers on this topic, I have yet to find a solution that works for my specific case. Imagine having an object like this: $scope.person = {name: 'Peter', category1: null, category2: null}; Another variable r ...

Would it be considered improper to implement an endless loop within a Vue.js instance for the purpose of continuously generating predictions with Tensorflow.js?

In my project, I am leveraging different technologies such as Tensorflow.js for training and predicting foods, Web API to access the webcam in my notebook, and Vue.js to create a simple web page. Within the addExample() method, there is an infinite loop r ...

Implementing file change detection using view model in Angular

When using the input type file to open a file and trigger a function on change, you can do it like this: <input type="file" multiple="multiple" class="fileUpload" onchange="angular.element(this).scope().fileOpened(this)" /> The functi ...

Transferring information from a Jade file to a Node.js server

I'm currently working on creating a data object within my Jade view page that will be used in my server-side JS. The data object involves dynamic HTML generation that inserts input boxes based on user input. function addDetail() { var det ...