javascript – chrome.runtime.sendMessage from background script does not send populated array to content script

I am working on a Chrome Extension that will grab all of the URLs in an email and the sender’s email address, send them to the background script, make an API call, and send the results back to the content script where the content script manipulates the CSS of the given URL or email based on the response from the API. I am struggling with this because I am wondering where to add the chrome.runtime.onMessage.addListener so I can manipulate the CSS of the given URL. I build an array of URLs that I then send over to the background script where I loop through each one and create an array of true or false values ​​that I eventually want to send back to the content script. I can see that the arrays in the background script are populated however when I read the message they show up undefined. Why is the background script sending empty arrays when I can clearly see in the console that the arrays are populated before calling returnURLMessage('URL', validatedURLS, riskScores);?

content.js

var senderEmail;
var emailBody;
var currentURL;

/* Listens for when the active history entry changes while the user navigates within
mail.google.com/* This will cause the extension to execute whenever a user loads a new email*/
window.addEventListener('popstate', function () {
  /* Time used to ensure the full page has loaded */
  setTimeout(() => {
        /* Grabs the Senders Email based on the 'go' class
          Note: This is only valid for Google Mail in Google Chrome*/
        senderEmail = document.getElementsByClassName("go").item(0);
        /* Calls the ValidateEmail function
           Checks to ensure that an email address has been grabbed */
        if (senderEmail != null) {
          ValidateEmail(senderEmail);
        } else {
          console.log("No email address.")
        }

        /* Email Body for Google Mail has an id=:2h
          Note: This is only valid for Google Mail in Google Chrome */
        emailBody = document.getElementById(":2h");
        /* Calls the ValidateURLS Function */
        ValidateURLS(emailBody);
    }, 400);
})

/* Listens for a window load event (i.e. Will execute whenever the user
  refreshes the page since popstate does not work on refresh events.) */
window.addEventListener('load', function () {
      /* Time used to ensure the full page has loaded */
      setTimeout(() => {
            /* Grabs the Senders Email based on the 'go' class
              Note: This is only valid for Google Mail in Google Chrome*/
            senderEmail = document.getElementsByClassName("go").item(0);
            /* Calls the ValidateEmail function
               Checks to ensure that an email address has been grabbed */
            if (senderEmail != null) {
              ValidateEmail(senderEmail);
            } else {
              console.log("No email address.")
            }

            /* Email Body for Google Mail has an id=:2h
              Note: This is only valid for Google Mail in Google Chrome */
            emailBody = document.getElementById(":2h");

            /* Calls the ValidateURLS Function */
            ValidateURLS(emailBody);
        }, 400);
})

function ValidateEmail(mail)
{
  /* Takes the innerText of the mail object */
  emailToValidate = mail.innerText;
/* Strips off the < and > from the string */
  emailToValidate = emailToValidate.replace(/[><]/g, '');
  console.log(emailToValidate);

  /* Sends the emailToValidate as a message to background.js to
  execute an API call. Note: API calls are not allowed in content.js files*/
  chrome.runtime.sendMessage({"type": "email", "emailToValidate": emailToValidate}, function(response) {
      console.log("contentscript sending email");
    });

}

function ValidateURLS(url)
{
  var listOfURLS = [];
  /* Creates a NodeList of all the 'a' tags in the URL Object */
  myNodeList = url.querySelectorAll("a");

  /* Loops through each a tag in the NodeList and
    attempts to validate it */
  for (let i = 0; i < myNodeList.length; i++) {
    /* Sends the emailToValidate as a message to background.js to
    execute an API call. Note: API calls are not allowed in content.js files*/
    url = String(myNodeList[i]).replace(/^https?:///, 'https%3A%2F%2F');
    url = url.split("/")[0];
    listOfURLS.push(url);
    console.log(url);
  }
  chrome.runtime.sendMessage({"type": "URL", "urlToValidate": listOfURLS}, function(response) {
      console.log("contentscript sending URL");
    });
}

/* Waits for a response from the background.js to apply the CSS to the
senders email based on validity */
chrome.runtime.onMessage.addListener(
  function(request, sender) {
    if (request.type == "email") {
        console.log("Contentscript has received an email message from from background script: " + request.message);
        if (request.message) {
          console.log("Valid Email " + request.risk_rating)
          senderEmail.textContent += " [" + request.risk_rating + "]/[4]";
          senderEmail.style.color = "green";
        } else {
          console.log("Invalid Email " + request.risk_rating)
          senderEmail.textContent += " [" + request.risk_rating + "]/[4]";
          senderEmail.style.color = "red";
        }
    }
    else if (request.type == "URL") {
      console.log("Contentscript has received a URL message from from background script: " + request.message);
/* Both values below show up undefined, but are defined in the background.js */
      console.log(request.risk_ratings);
      console.log(request.messages);
      for (let i = 0; i < request.risk_ratings.length; i++) {
        console.log("URL From content.js: " + request.messages[i])
        console.log("Risk Rating From content.js: " + request.risk_ratings[i])
      }
    }
  });

background.js

chrome.runtime.onMessage.addListener(function(request, sender) {
/* If the Request is of type email */
  if (request.type == "email") {
    /* API Overview https://www.ipqualityscore.com/documentation/email-validation/overview */
    $.getJSON('https://ipqualityscore.com/api/json/email/<api_key>/' + request.emailToValidate, function( json ) {
      console.log( "Checking email: " + request.emailToValidate);
      /* Boolean Value for Email Validity */
      var isValid = false;
      requestType="email";
  /* If Else statement evaluates the email address based on the response from the api.*/
      if (json.valid && !json.disposable && json.overall_score >= 3) {
        console.log("Valid Email Address")
        isValid = true;
        returnMessage(request.type, isValid, json.overall_score)
      } else {
        console.log("Invalid Email Address")
        isValid = false;
        returnMessage(request.type, isValid, json.overall_score)
      }
     });
   }
   /* If the Request is of type URL */
   else if (request.type == 'URL') {
     /* API Overview https://www.ipqualityscore.com/documentation/malicious-url-scanner-api/overview */
     for (let i = 0; i < request.urlToValidate.length; i++) {
//       console.log(request.urlToValidate[i]);
       $.getJSON('https://ipqualityscore.com/api/json/url/DxCYsYizITD6xdeRDgjHj1QWzDTVY49v/' + request.urlToValidate[i], function( json ) {
         console.log( "Checking URL: " + request.urlToValidate[i]);
         /* Boolean Value for Email Validity */
//         var isURLValid = false;
     /* If Else statement evaluates the URL address based on the response from the api.
     Reponse from the API can be described as such:
       phishing - Is this URL associated with malicious phishing behavior? - Booblean
       malware - Is this URL associated with malware or viruses? - Booblean
       parking - Is the domain of this URL currently parked with a for sale notice? - Boolean
       spamming - Is the domain of this URL associated with email SPAM or abusive email addresses? - Boolean
       risk_score -
         Risk Scores < 80 - Safe
         Risk Scores >= 75 - suspicious - usually due to patterns associated with malicious links.
         Risk Scores >= 85 - high risk - strong confidence the URL is malicious.
         Risk Scores = 100 AND Phishing = "true" OR Malware = "true" - indicates confirmed malware or phishing activity in the past 24-48 hours.
     */
     // console.log(json.phishing);
     // console.log(json.malware);
     // console.log(json.parking);
     // console.log(json.spamming);

         if (!json.phishing && !json.malware && !json.parking && !json.spamming && json.risk_score < 80) {
           console.log("Valid URL Address")
           validatedURLS.push(true);
           riskScores.push(json.risk_score);
//           returnMessage(request.type, isURLValid, json.risk_score)
         } else {
           console.log("Invalid URL Address")
           validatedURLS.push(false);
           riskScores.push(json.risk_score);
//           returnMessage(request.type, isURLValid, json.risk_score)
         }
        });
    }
    console.log(validatedURLS) //Has values
    console.log(riskScores) // Has values
    returnURLMessage('URL', validatedURLS, riskScores);
   }
});

/* Sends a message back to content.js based on the email Validity.
- False if Invalid
- True if Valid */
function returnMessage(requestType, boolValue, risk_rating)
{
 chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {type: requestType, message: boolValue, risk_rating: risk_rating}, function(response) {
    console.log("Background script is sending a message to contentscript: " + boolValue);
  });
});
}

function returnURLMessage(requestType, boolValues, risk_ratings)
{
 chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
  chrome.tabs.sendMessage(tabs[0].id, {type: requestType, "messages": boolValues, "risk_rating": risk_ratings}, function(response) {
    console.log("Background script is sending a message to contentscript: " + boolValues);
  });
});
}

{
manifest.json

"background": {
    "persistent": false,
    "scripts": ["jQuery.js", "background.js"]
},
"content_scripts": [{
    "matches": ["https://mail.google.com/*"],
    "js":      ["jQuery.js", "content.js"]
}],
"permissions": ["tabs", "https://ipqualityscore.com/*"]
}

Leave a Comment