从扩展上下文菜单复制到剪贴板而不使用“脚本”或“content_scripts”?

Copy to the clipboard from extension context menu without using `scripting` or `content_scripts`?

提问人:Peter V. Mørch 提问时间:4/10/2023 更新时间:4/11/2023 访问量:159

问:

背景:我想写一个扩展,右键单击扩展图标并单击上下文菜单项将某些内容复制到剪贴板。

但我也想避免使用权限或注入 ,因为某些公司环境不允许它(有充分的理由)。scriptingcontent_scriptsmanifest.json

但是,如果我不使用 或 ,我如何从处理程序复制到剪贴板?在后台脚本中两者都不可用(其中 和 都是未定义的),并且没有要向其发送消息的页面,因为无法从后台脚本打开页面,并且我不想使用内容注入。chrome.contextMenus.onClickedscriptingcontent_scriptsdocument.execCommandnavigator.clipboard.writedocumentnavigator.clipboardaction.default_popup

有什么想法吗?

谷歌浏览器扩展程序

评论

0赞 Peter V. Mørch 4/11/2023
@wOxxOm:谢谢。这简直太棒了!如果你愿意把它变成一个答案,我会接受的。

答:

0赞 Peter V. Mørch 4/11/2023 #1

cookbook.offscreen-clipboard-write 示例是使用 chrome.offscreen 的完整示例。意义在于,屏幕外正是为此目的而创建的。

这是一个摘要,但有关更多详细信息,请参阅上述两个链接:

首先,将 中的权限添加到 中。"offscreen"manifest.json

然后在:background.js

// This could also be chrome.contextMenus.onClicked.addListener()
chrome.action.onClicked.addListener(async () => {
  await chrome.offscreen.createDocument({
    url: chrome.runtime.getURL('offscreen.html'),
    reasons: [chrome.offscreen.Reason.CLIPBOARD],
    justification: 'Need to copy data to the clipboard',
  });
  chrome.runtime.sendMessage({
    type: 'copy-data-to-clipboard',
    target: 'offscreen-doc',
    data: 'put this string on the clipboard'
  });
});

offscreen.html有:

<!DOCTYPE html>
<textarea id="text"></textarea>
<script src="offscreen.js"></script>

和:offscreen.js

chrome.runtime.onMessage.addListener(handleMessages);

async function handleMessages(message) {
  if (message.target !== 'offscreen-doc') {
    return;
  }

  switch (message.type) {
    case 'copy-data-to-clipboard':
      handleClipboardWrite(message.data);
      break;
    default:
      console.warn(`Unexpected message type received: '${message.type}'.`);
  }
}

const textEl = document.querySelector('#text');

async function handleClipboardWrite(data) {
  try {
    if (typeof data !== 'string') {
      throw new TypeError(
        `Value provided must be a 'string', got '${typeof data}'.`
      );
    }

    textEl.value = data;
    textEl.select();
    document.execCommand('copy');
  } finally {
    window.close();
  }
}