这是我第一次构建 Google Chrome 扩展,所以我仍在学习,并且可能会做一些愚蠢的事情。感谢您提前提供的任何帮助。
一些背景知识:
Google Cloud Console IAM 管理页面 (https://console.cloud.google.com/iam-admin/) 根据项目编号列出了原则。例如,原则可能会列为 [email protected],其中 123456789012 是项目 ID。显然,123456789012 不太适合人类阅读,所以我想构建一个 chrome 扩展,它可以在包含项目 id 的字符串上创建工具提示,其中工具提示文本将是项目名称。
我创建了一个
background.js
脚本。该脚本用于打开/关闭 chrome 扩展。
let extensionEnabled = false; // Variable to track extension state
chrome.action.onClicked.addListener((tab) => {
extensionEnabled = !extensionEnabled; // Toggle extension state
// Save the state of extensionEnabled to storage
chrome.storage.local.set({ isEnabled: extensionEnabled });
// Update the extension icon to indicate the current state
const iconPath = extensionEnabled
? { '16': 'images/icon_enabled16.png', '48': 'images/icon_enabled48.png', '128': 'images/icon_enabled128.png' }
: { '16': 'images/icon16.png', '48': 'images/icon48.png', '128': 'images/icon128.png' };
chrome.action.setIcon({ path: iconPath });
});
我还创建了一个包含脚本逻辑的
contentScript.js
文件。
const wordMap = {
// At present I am just hard-coding the project id number and project name
"123456789012": "project-name",
};
let extensionEnabled = false;
// Load the state from storage
chrome.storage.local.get('isEnabled', (result) => {
extensionEnabled = result.isEnabled || false;
if (extensionEnabled) processPage();
});
function processPage() {
// Create a new style element
const style = document.createElement('style');
// Set the CSS for tooltips
style.textContent = `
...
`;
// Append the style element to the head of the document
document.head.appendChild(style);
// Find occurrences of keys in wordMap in the text nodes of the document and put them in the textNodes array
const textNodes = [];
findTextNodes(document.body, textNodes);
// This creates tooltips for all nodes in the textNodes array
createTooltips(textNodes);
}
我已经在测试 HTML 文档上测试了逻辑,并且
processPage()
在简单的静态 HTML 文档上可以正常工作。
但是,该扩展在 Google 云控制台中使用时无法正常工作。
textNodes
数组从未填充任何节点。我怀疑这是因为在 Google 控制台 IAM 页面中,它们是由页面的 JS 脚本填充/水化的。
通过谷歌搜索,我在网上发现了一些提示,这是因为该扩展在隔离环境中运行。我尝试将清单中的
world
键更改为 MAIN
。然而,这会导致扩展中出现错误:Uncaught TypeError: Cannot read properties of undefined (reading 'local')
对于行chrome.storage.local.get('isEnabled', (result)
这是我的清单文件:
{
"manifest_version": 3,
"name": "GCP Project ID Tooltip Chrome Extension",
"version": "0.1",
"description": "Chrome Extension that adds a tooltip with project names over project ID's in GCP console webpages.",
"action": {},
"permissions": [
"cookies",
"activeTab",
"storage",
"scripting"
],
"host_permissions": [
"https://console.cloud.google.com/*"
],
"optional_host_permissions":[
"https://*/*",
"http://*/*"
],
"background": {
"service_worker": "background.js",
"type": "module"
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"contentScript.js"
],
"all_frames": true,
"world": "MAIN"
}
],
"icons": {
"16": "images/icon16.png",
"48": "images/icon48.png",
"128": "images/icon128.png"
}
}
我的几个问题是:
"world": "MAIN"
吗?还是ISOLATED
足够好?
Cannot read properties of undefined (reading 'local')
问题,但随后我会发现 textNodes
数组未填充?host_permissions
还是optional_host_permissions
content_scripts.matches
?我怀疑是https://console.cloud.google.com/
,但我想确认一下。再次感谢您的见解!
根据问题评论,我能够使用 MutationObserver 实现解决方案。我只是按照文档中的示例,为我的用例实现它。需要注意的是 - 如果您刚刚学习 - MutationObserver 必须位于您的内容脚本中(而不是 Service Worker 后台脚本)。
这是我的清单文件的一部分,用于回答我的其他问题:
"host_permissions": [
"https://console.cloud.google.com/*"
],
"background": {
"service_worker": "src/background.js",
"type": "module"
},
"content_scripts": [
{
"matches": [
"https://console.cloud.google.com/*"
],
"css": [
"css/tooltip.css"
]
}
],