Chrome扩展消息通信异常:google_login请求报错,clicked_browser_action正常
我在Chrome扩展中,从popup对应的main.js向background.js发送消息时,遇到错误:Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
发送的两种消息里,clicked_browser_action能正常工作,但google_login触发上述错误。
main.js
function processPage(root) { document.getElementById('submit-btn').addEventListener('click', submitButtonClicked); document.getElementById('google-signin-btn').addEventListener('click', googleSiginButtonClicked); chrome.runtime.onMessage.addListener(receiveMessage); } function appendText(text) { let node = document.getElementById('web-content'); node.innerHTML += text; } function submitButtonClicked() { appendText("submit button clicked"); sendMessage({txt: "clicked_browser_action"}); } function googleSiginButtonClicked() { console.log("sending login message"); sendMessage({txt: "google_login"}); } function receiveMessage(request, sender, sendResponse) { if (request.txt === "page_content") { appendText(request.content); } } // 当前实现:向活跃标签页发送消息 function sendMessage(response) { let params = {active: true, currentWindow: true}; chrome.tabs.query(params, function(tabs) { chrome.tabs.sendMessage(tabs[0].id, response); }); } if (document.readyState === "complete") { processPage(document.body); } else { window['onload'] = function () { processPage(document.body); } }
background.js
let user_signed_in = false; const CLIENT_ID = "MY_CLIENT_ID" const REDIRECT_URI = chrome.identity.getRedirectURL("oauth2"); function create_oauth() { let auth_url = `https://accounts.google.com/o/oauth2/v2/auth?` var auth_params = { client_id: CLIENT_ID, redirect_uri: REDIRECT_URI, response_type: 'token', scope: "https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid", }; const url = new URLSearchParams(Object.entries(auth_params)); auth_url += url; return auth_url; } function googleLoginListener(request, sender, sendResponse) { console.log("googleLoginListener: ", request); if (request.txt === 'google_login') { if (user_signed_in) { return; } else { chrome.identity.launchWebAuthFlow({ url: create_oauth(), interactive: true }, function (redirect_uri) { sendResponse('success') }) } } } function processPage() { console.log("background service active"); chrome.runtime.onMessage.addListener(googleLoginListener); } processPage();
main.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="main.js"></script> </head> <body> <div style="width: 200px; height: 200px;"> Displaying web content below </div> <div id="web-content"></div> <button id="submit-btn">PRINT CONTENT</button> <button id="google-signin-btn">GOOGLE SIGN_IN</button> </body> </html>
问题根源与修复
1. 消息发送API使用错误
你的sendMessage函数调用了chrome.tabs.sendMessage,这是给当前标签页的content script发消息的API,但你要通信的目标是background.js,应该使用chrome.runtime.sendMessage直接与background建立通信。
clicked_browser_action看似正常,是因为当前标签页的content script中大概率监听了这个消息,而google_login没有对应的content script监听,因此触发“接收端不存在”的错误。
修改后的sendMessage函数:
// 直接向background发送消息 function sendMessage(response) { chrome.runtime.sendMessage(response, (res) => { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError); } else { console.log("收到background响应:", res); } }); }
2. 异步响应的通道保持
background中的googleLoginListener调用了异步APIchrome.identity.launchWebAuthFlow,需要在监听函数中返回true,告知Chrome保留消息通道直到sendResponse被调用,否则会提前断开连接导致错误。
修改后的googleLoginListener:
function googleLoginListener(request, sender, sendResponse) { console.log("googleLoginListener: ", request); if (request.txt === 'google_login') { if (user_signed_in) { sendResponse('already signed in'); return; } else { chrome.identity.launchWebAuthFlow({ url: create_oauth(), interactive: true }, function (redirect_uri) { user_signed_in = true; sendResponse('success') }); // 返回true表示异步响应,保持通道开放 return true; } } }
3. 验证manifest权限
确保manifest.json中声明了必要的权限和OAuth2配置:
{ "permissions": ["identity", "tabs"], "oauth2": { "client_id": "你的CLIENT_ID", "scopes": [ "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "openid" ] } }
内容的提问来源于stack exchange,提问作者PiyushK

