Chrome扩展onMessage与onUpdated触发异常:非预期执行脚本问题
Chrome扩展表单自动填充与页面跳转逻辑问题
我正在开发一款Chrome扩展,用于在亚利桑那州政府网站(azdot.gov)自动填充表单并导航至提交页面,目前遇到逻辑触发的问题:
- 点击扩展图标后,调用脚本在
www.azdot.gov/home页面的搜索栏输入内容并点击搜索按钮,这部分仅部分生效 - 点击搜索按钮后,脚本会向扩展发送
action: "clicked"的消息,我希望仅在收到该消息且新页面(www.azdot.gov/search)加载完成后,运行第二个测试脚本(用alert显示页面标题) - 当前代码无报错,但alert会在手动导航任意页面时弹出,没有实现“收到消息+页面加载完成”的双重触发逻辑
- 因为脚本无法跨页面持续运行,所以采用
runtime.onMessage配合tabs.onUpdated的方案
以下是当前代码:
manifest.json
{ "name": "PVA WF1", "version": "0.1", "description": "Working extension but sendMessage portion not functional.", "manifest_version": 3, "author": "hobbledcobbled", "action": { "default_title": "PVA WF1" }, "permissions": [ "storage", "activeTab", "scripting", "tabs" ], "host_permissions": [ "https://azdot.gov/home" ], "background": { "service_worker": "background.js" } }
background.js
chrome.action.onClicked.addListener(async () => { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); await chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ['claimSubmitStart.js'] }); }); try { chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { chrome.tabs.onUpdated.addListener(function (tabdId, changeInfo, tab) { if (changeInfo.status == 'complete' && message.action === 'clicked') { chrome.scripting.executeScript({ target: { tabId: tab.id }, func: () => { alert(document.title); }, }); } }); }); } catch (e) { alert(e); }
claimSubmitStart.js
const searchInput = document.getElementById("edit-keyword"); const searchBtn = document.getElementById("edit-submit-solr-search"); if (searchInput && searchBtn) {(n async () => { const message = { action: "clicked" }; await chrome.runtime.sendMessage(message); })(); }; searchInput.value = "license"; searchBtn.click();
问题根源
当前代码的错误在于:每次收到runtime.onMessage时,都会新增一个tabs.onUpdated监听器,且该监听器未绑定特定tab、也不会自动移除。后续任何页面加载完成时,所有之前添加的监听器都会触发,导致alert误弹出。
修复方案
- 记录触发搜索的tab ID,只监听目标tab的更新
- 使用一次性监听器,页面加载完成后立即移除,避免重复触发
- 修正
claimSubmitStart.js的语法错误
修改后的background.js
chrome.action.onClicked.addListener(async () => { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); await chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ['claimSubmitStart.js'] }); }); let targetTabId = null; chrome.runtime.onMessage.addListener((message, sender) => { if (message.action === 'clicked') { // 记录触发搜索的tab ID targetTabId = sender.tab.id; // 添加一次性监听器 const onTabUpdated = (tabId, changeInfo, tab) => { // 仅处理目标tab且页面加载完成的情况 if (tabId === targetTabId && changeInfo.status === 'complete') { chrome.scripting.executeScript({ target: { tabId: tab.id }, func: () => { alert(document.title); }, }); // 移除监听器,防止重复触发 chrome.tabs.onUpdated.removeListener(onTabUpdated); // 重置目标tab ID targetTabId = null; } }; chrome.tabs.onUpdated.addListener(onTabUpdated); } });
修改后的claimSubmitStart.js
const searchInput = document.getElementById("edit-keyword"); const searchBtn = document.getElementById("edit-submit-solr-search"); if (searchInput && searchBtn) { (async () => { const message = { action: "clicked" }; await chrome.runtime.sendMessage(message); })(); searchInput.value = "license"; searchBtn.click(); }
额外优化建议
- 扩展的
host_permissions需要添加https://azdot.gov/search,否则无法在搜索页面注入脚本 - 可以在发送消息时传递目标页面URL,在监听器里额外判断URL匹配,进一步避免误触发
内容的提问来源于stack exchange,提问作者hobbledcobbled
相关产品推荐
相关产品推荐

