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

如何在Manifest V3版Chrome扩展中集成Google Picker API?

在Chrome扩展Manifest V3中集成Google Picker API的可行方案

由于Manifest V3严格限制远程脚本加载,直接引入https://apis.google.com/js/api.js会触发CSP拦截,以下是两种经过验证的解决方案:

方案一:使用Sandbox iframe加载Picker UI

这是目前最稳妥的方式,通过隔离的iframe绕过主扩展的CSP限制,同时保留官方Picker的完整功能:

1. 配置Manifest.json

添加sandbox权限,指定Picker专用页面的宽松CSP:

{
  "manifest_version": 3,
  "name": "Drive文件夹选择器",
  "version": "1.0",
  "permissions": ["identity", "storage"],
  "oauth2": {
    "client_id": "你的OAuth客户端ID",
    "scopes": ["https://www.googleapis.com/auth/drive.file"]
  },
  "sandbox": {
    "pages": ["picker.html"],
    "content_security_policy": "script-src 'self' https://apis.google.com; object-src 'none'"
  },
  "action": {
    "default_popup": "popup.html"
  }
}

2. 创建Picker专用页面(picker.html)

专门用于加载Google Picker脚本和初始化UI:

<!DOCTYPE html>
<html>
<head>
  <script src="https://apis.google.com/js/api.js"></script>
  <script src="picker.js"></script>
</head>
<body>
  <div id="picker"></div>
</body>
</html>

3. 编写Picker逻辑(picker.js)

通过postMessage与主扩展页面通信,接收授权token并返回选中的文件夹ID:

let authToken;

// 接收来自主页面的授权token
window.addEventListener('message', (event) => {
  if (event.origin !== window.parent.location.origin) return;
  if (event.data.type === 'setAuthToken') {
    authToken = event.data.token;
    initPicker();
  }
});

// 初始化Google Picker
function initPicker() {
  gapi.load('picker', () => {
    const picker = new google.picker.PickerBuilder()
      .setOAuthToken(authToken)
      .addView(google.picker.ViewId.FOLDERS) // 仅显示文件夹
      .setCallback(pickerCallback)
      .build();
    picker.setVisible(true);
  });
}

// 处理选中事件,向主页面发送结果
function pickerCallback(data) {
  if (data.action === google.picker.Action.PICKED) {
    const folderId = data.docs[0].id;
    window.parent.postMessage(
      { type: 'folderSelected', folderId: folderId },
      window.parent.location.origin
    );
  }
}

4. 在主扩展页面嵌入iframe并通信

以popup.html为例,获取授权token后加载iframe:

<!DOCTYPE html>
<html>
<head>
  <style>iframe { width: 100%; height: 400px; border: none; }</style>
</head>
<body>
  <div id="picker-container"></div>
  <script src="popup.js"></script>
</body>
</html>

popup.js代码:

// 获取Google授权token
chrome.identity.getAuthToken({ interactive: true }, (token) => {
  if (chrome.runtime.lastError) {
    console.error(chrome.runtime.lastError);
    return;
  }

  // 创建并加载Picker iframe
  const iframe = document.createElement('iframe');
  iframe.src = chrome.runtime.getURL('picker.html');
  document.getElementById('picker-container').appendChild(iframe);

  // 监听Picker返回的选中结果
  window.addEventListener('message', (event) => {
    if (event.origin !== window.location.origin) return;
    if (event.data.type === 'folderSelected') {
      console.log('选中的文件夹ID:', event.data.folderId);
      // 此处可继续处理文件上传逻辑
      iframe.remove(); // 可选:关闭Picker
    }
  });

  // 向iframe发送授权token
  iframe.onload = () => {
    iframe.contentWindow.postMessage(
      { type: 'setAuthToken', token: token },
      window.location.origin
    );
  };
});

方案二:基于Drive REST API自定义文件夹选择UI

如果不想处理iframe通信,可以直接用你已有的Drive API调用能力,自己实现文件夹选择界面:

  1. 调用Drive REST API的files.list接口,筛选文件夹:
async function getDriveFolders(token) {
  const response = await fetch(
    'https://www.googleapis.com/drive/v3/files?q=mimeType%3D%27application%2Fvnd.google-apps.folder%27&fields=files(id,name)',
    { headers: { Authorization: `Bearer ${token}` } }
  );
  return await response.json();
}
  1. 用HTML/CSS渲染文件夹列表,添加选择交互逻辑,完全符合Manifest V3的CSP限制。

注意事项

  • 确保OAuth客户端ID已正确配置,并添加了Chrome扩展的应用ID作为授权来源。
  • 使用postMessage时必须验证消息来源,避免安全风险。
  • Sandbox页面无法直接调用Chrome扩展API,所有与扩展的交互必须通过postMessage完成。

内容的提问来源于stack exchange,提问作者Віталій Тимів

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 16:57:27