You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展:如何通过代码让文档获焦以实现剪贴板粘贴?

解决Chrome扩展切换标签后执行粘贴脚本的文档失焦问题

问题场景

开发Chrome扩展时,通过快捷键(如alt+o)切换到指定标签页并触发剪贴板粘贴操作,标签页成功激活但执行粘贴脚本时抛出异常:

DOMException: Document is not focused.

原因是chrome.tabs.update仅激活标签页,无法立即让页面文档获得焦点,而navigator.clipboard.read和剪贴板事件触发需要文档处于聚焦状态。

解决方案

方案1:等待文档聚焦后执行粘贴

在内容脚本的粘贴函数中,添加等待逻辑,确保文档获得焦点后再执行操作:

// paste.js 修改后
async function pasteContent() {
  try {
    // 等待文档聚焦,轮询检查或监听事件
    if (!document.hasFocus()) {
      await new Promise(resolve => {
        const onFocus = () => {
          document.removeEventListener('focus', onFocus);
          resolve();
        };
        document.addEventListener('focus', onFocus);
      });
    }

    // 原粘贴逻辑
    const wizElement = document.querySelector('c-wiz')
    const clipboardItems = await navigator.clipboard.read()
    const firstItem = clipboardItems[0]
    const blob = await firstItem.getType('image/png')
    const file = new File([blob], 'image.png', { type: 'image/png' })

    const dataTransfer = new DataTransfer()
    dataTransfer.items.add(file)

    const pasteEvent = new ClipboardEvent('paste', {
      bubbles: true,
      cancelable: true,
      clipboardData: dataTransfer,
    })

    wizElement.dispatchEvent(pasteEvent)
  } catch (e) { console.log(e) }
}

方案2:利用标签激活事件+消息传递

通过监听标签激活事件,确保标签完全激活后再通知内容脚本执行粘贴,避免过早注入脚本:

// background.js 修改后
async function switchToTabAndPasteContent() {
  const tab = (await chrome.tabs.query({})).filter(tab => tab.title.toLowerCase().includes('my page'))[0]

  await chrome.windows.update(tab.windowId, { focused: true })
  await chrome.tabs.update(tab.id, { active: true })

  // 监听标签激活完成事件
  const activationListener = async (activeInfo) => {
    if (activeInfo.tabId === tab.id) {
      chrome.tabs.onActivated.removeListener(activationListener)
      // 向内容脚本发送粘贴指令
      await chrome.tabs.sendMessage(tab.id, { action: 'triggerPaste' })
    }
  }
  chrome.tabs.onActivated.addListener(activationListener)
}
// paste.js 添加消息监听
chrome.runtime.onMessage.addListener((message) => {
  if (message.action === 'triggerPaste') {
    pasteContent()
  }
})

async function pasteContent() {
  // 原粘贴逻辑...
}

方案3:在Background中读取剪贴板(需额外权限)

将剪贴板读取逻辑移至Background Service Worker,避免内容脚本因失焦无法读取剪贴板,再将内容传递给页面执行粘贴:

// manifest.json 添加权限
{
  "permissions": [ "tabs", "scripting", "activeTab", "clipboardRead" ],
  // 其他配置...
}
// background.js 修改后
async function switchToTabAndPasteContent() {
  const tab = (await chrome.tabs.query({})).filter(tab => tab.title.toLowerCase().includes('my page'))[0]

  await chrome.windows.update(tab.windowId, { focused: true })
  await chrome.tabs.update(tab.id, { active: true })

  // 在Background读取剪贴板
  try {
    const clipboardItems = await navigator.clipboard.read()
    const firstItem = clipboardItems[0]
    const blob = await firstItem.getType('image/png')
    
    // 将Blob转为Base64传递给内容脚本
    const reader = new FileReader()
    reader.onload = async () => {
      const base64Data = reader.result.split(',')[1]
      await chrome.scripting.executeScript({
        target: { tabId: tab.id },
        func: (base64) => pasteFromBase64(base64),
        args: [base64Data]
      })
    }
    reader.readAsDataURL(blob)
  } catch (e) { console.log(e) }
}
// paste.js 添加Base64转文件并粘贴的函数
function pasteFromBase64(base64) {
  try {
    const wizElement = document.querySelector('c-wiz')
    const byteChars = atob(base64)
    const byteArr = new Uint8Array(byteChars.length)
    for (let i = 0; i < byteChars.length; i++) {
      byteArr[i] = byteChars.charCodeAt(i)
    }
    const blob = new Blob([byteArr], { type: 'image/png' })
    const file = new File([blob], 'image.png', { type: 'image/png' })

    const dataTransfer = new DataTransfer()
    dataTransfer.items.add(file)

    const pasteEvent = new ClipboardEvent('paste', {
      bubbles: true,
      cancelable: true,
      clipboardData: dataTransfer,
    })

    wizElement.dispatchEvent(pasteEvent)
  } catch (e) { console.log(e) }
}

内容的提问来源于stack exchange,提问作者vdegenne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 10:17:23