Chrome扩展Gmail插件开发:自定义元素chrome.runtime.getURL报错解决
问题原因
你注入到页面主世界的gmail-compose-assistant-element.js无法访问chrome.runtime.getURL API——该API仅在Chrome扩展的隔离上下文(如content script、service worker)中可用,页面主世界(普通网页脚本)没有权限调用扩展API,因此出现报错。
解决方案
以下两种方案均可解决该问题:
方案一:内联HTML与CSS资源
直接将自定义元素的HTML结构和CSS样式写入脚本,避免依赖外部资源请求,彻底绕开chrome.runtime.getURL的使用。
修改custom-elements/gmail-compose-assistant-element.js:
const template = document.createElement('template'); // 内联原HTML文件内容 const inlineHTML = ` <div class="assistant-container"> <button class="assistant-trigger">助手选项</button> <ul class="assistant-dropdown"> <li class="dropdown-item">选项1</li> <li class="dropdown-item">选项2</li> </ul> </div> `; // 内联原CSS文件内容 const inlineStyle = document.createElement('style'); inlineStyle.textContent = ` .assistant-container { position: relative; display: inline-block; } .assistant-trigger { padding: 6px 12px; border: 1px solid #dadce0; border-radius: 4px; background: white; cursor: pointer; margin-left: 8px; } .assistant-dropdown { position: absolute; top: 100%; right: 0; margin: 8px 0; padding: 0; list-style: none; background: white; border: 1px solid #dadce0; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); display: none; } .dropdown-item { padding: 8px 16px; cursor: pointer; } .dropdown-item:hover { background: #f1f3f4; } `; template.innerHTML = inlineHTML; template.content.prepend(inlineStyle); class CustomGmailComposeAssistant extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); // 绑定下拉菜单逻辑 const trigger = this.shadowRoot.querySelector('.assistant-trigger'); const dropdown = this.shadowRoot.querySelector('.assistant-dropdown'); trigger.addEventListener('click', () => { dropdown.style.display = dropdown.style.display === 'none' ? 'block' : 'none'; }); // 点击外部关闭下拉 document.addEventListener('click', (e) => { if (!this.contains(e.target)) { dropdown.style.display = 'none'; } }); } } window.customElements.define('custom-gmail-compose-assistant', CustomGmailComposeAssistant);
方案二:在Content Script中预获取资源URL并传递给主世界
利用Content Script可访问扩展API的特性,提前获取HTML/CSS资源的可访问URL,再传递给注入到主世界的自定义元素脚本。
修改gmail-compose-assistant.js:
// 1. 在Content Script中获取资源URL const htmlResourceUrl = chrome.runtime.getURL('/custom-elements/gmail-compose-assistant-element.html'); const cssResourceUrl = chrome.runtime.getURL('/custom-elements/gmail-compose-assistant-element.css'); // 2. 构造主世界脚本内容,注入预获取的URL const scriptContent = ` const htmlUrl = "${htmlResourceUrl}"; const cssUrl = "${cssResourceUrl}"; const template = document.createElement('template'); fetch(htmlUrl).then((response) => response.text().then((html) => { template.innerHTML = html; const styleSheetLink = document.createElement('link'); styleSheetLink.rel = 'stylesheet'; styleSheetLink.href = cssUrl; template.content.prepend(styleSheetLink); }) ); class CustomGmailComposeAssistant extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.shadowRoot.appendChild(template.content.cloneNode(true)); } } window.customElements.define('custom-gmail-compose-assistant', CustomGmailComposeAssistant); `; // 3. 注入脚本到页面主世界 const script = document.createElement('script'); script.type = 'module'; script.textContent = scriptContent; document.body.appendChild(script); // 原观察者逻辑保持不变 const observerConfig = { childList: true, }; const observer = new MutationObserver(observeDocumentBody); observer.observe(document.body, observerConfig); function injectDummyText(element, index) { const newTabledataRef = document.querySelector('#newTableData' + index); const tableRow = element.querySelector('tr'); if (!newTabledataRef) { const tableData = tableRow.insertCell(1); const customElement = document.createElement('custom-gmail-compose-assistant'); tableData.appendChild(customElement); tableData.id = 'newTableData' + index; } } function observeDocumentBody() { const tableElemets = document.getElementsByClassName('IZ'); if (tableElemets.length) { Object.values(tableElemets).forEach((element, index) => { injectDummyText(element, index); }); } }
额外注意事项
- 确保
manifest.json中的web_accessible_resources配置正确,已将自定义元素相关资源列为可访问项(你的现有配置符合要求)。 - 主世界脚本无法直接调用任何Chrome扩展API,若后续需要与扩展通信,需通过
window.postMessage与Content Script交互,再由Content Script调用扩展API。
内容的提问来源于stack exchange,提问作者vijay s
相关产品推荐
相关产品推荐

