Search code examples
javascriptgoogle-chrome-extensionpermissions

How can I permanently grant permission for navigator.clipboard in a Chrome extension?


I'm trying to use navigator.clipboard.readText() in a tab opened by my Google Chrome extension. When I do, the below permission alert appears on every page load, even though I have granted the permission already:

Enter image description here

This is the relevant code:

<button onclick="getClipboardContents()">Add</button>

<script>
  async function getClipboardContents() {
    try {
      const text = await navigator.clipboard.readText();
      console.log('Pasted content: ', text);
    } catch (err) {
      console.error('Failed to read clipboard contents: ', err);
    }
  }
</script>

Is there a way to stop this message from appearing every time?


Solution

  • You don't specify how you are opening the page. The permission dialog indicates that you are accessing it via a file:// URL. Tabs, opened by an extension should have a chrome-extension:// URL and the permission dialog should show the name of your extension :

    enter image description here

    You need to add the clipboardRead permission to your manifest.json and open the tab with chrome.tabs.create() and chrome.runtime.getURL(). When done in this manner, the permission dialog should only appear on the first page load and not every time.

    Here is a minimal reproducible example :

    manifest.json

    {
      "manifest_version": 3,
      "name": "Clipboard Test",
      "version": "0.1",
      "permissions": [
        "clipboardRead"
      ],
      "action": {},
      "background": {
        "service_worker": "background.js"
      }
    }
    

    background.js

    chrome.action.onClicked.addListener(currentTab => {
      chrome.tabs.create({
        'url': chrome.runtime.getURL("test.html")
      });
    });
    

    test.html

    <!DOCTYPE html>
    <title> Clipboard Test </title>
    <button id="test"> TEST </button>
    <script src="clip.js"></script>
    

    clip.js

    const button = document.querySelector('button#test');
    
    async function paste() {
      let text = await navigator.clipboard.readText();
      alert(text);
    }
    
    button.addEventListener('click', paste);