Search code examples
javascriptgoogle-chrome-extension

Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist. Sending message from popup.js to background.js


I am constantly getting this error whenever I am trying to send message from popup.js (in my case main.js) to background.js. I am sending two types of messages clicked_browser_action and google_login. clicked_browser_action works fine but google_login gives the error shown below.

error while sending message

Below are the code snippets from different scripts

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");

    // ask for message
    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);
    }
}

// sends message to the active tab
function sendMessage(response) {
    // cannot get the tabs data from popup script
    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

// Google sign-in code
let user_signed_in = false;

const CLIENT_ID = "MY_CLIENT_ID"
const RESPONSE_TYPE = encodeURIComponent('token')
const REDIRECT_URI = chrome.identity.getRedirectURL("oauth2");
const STATE = encodeURIComponent('jsksf3')
const SCOPE = encodeURIComponent('openid')
const PROMPT = encodeURIComponent('consent')

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));
    url.toString();
    auth_url += url;
  
    return auth_url;
}

function googleLoginListener(request, sender, sendResponse) {
    console.log("googleLoginListener: ", request); // clicked_browser_action is coming here but not google_login
    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 class="" style="width: 200px; height: 200px;">
        Displaying web content below
    </div>
    <div class="" id="web-content"></div>
    <button id="submit-btn">PRINT CONTENT</button>
    <button id="google-signin-btn">GOOGLE SIGN_IN</button>
</body>
</html>

I have tried various solutions but none have worked, also it's weird that it is working for clicked_browser_action but not google_login which have the exact same code.


Solution

  • Figured it out, instead of sending to a particular tab if I send a generic message it is picked up by the background script

    using

    chrome.runtime.sendMessage({txt: "google_login"});
    

    instead of

    chrome.tabs.query(params, function(tabs) {
            chrome.tabs.sendMessage(tabs[0].id, {txt: "google_login"});
        });