1

I have been banging my head against a wall for the past two days to try and pass an array from my background.js script to my inject.js (content) script but I can't seem to figure it out.

I found this resource on SO that has the same problem: Pass array variable from background.js to content.js

Somehow I still can't seem to figure it out.. It seems he took a different approach than me since I am getting user input to create my array.

I am trying to send the userHash array from background.js to inject.js

Manifest.js

{
  "name": "Instagram Automated",
  "version": "1.0",
  "manifest_version": 2,
  "description": "One of the safest Instagram Automation tools on the market.",
  "homepage_url": "http://grantdarling.com",
  "background": {
    "scripts": [
      "background.js"
    ],
    "persistent": true
  },
  "browser_action": {
    "default_popup": "popup.html",
    "default_title": "Automated Instagram"
  },
  "permissions": [
    "tabs",
    "notifications",
    "storage",
    "http://www.instagram.com/",
    "https://www.instagram.com/"
  ]
}

popup.html

<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="popup.css">
  <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet">
</head>

<body>
  <div class="header-container">
    <h1 id="title">Automated Instagram</h1>
    <img id="insta-logo" src="media/Instagram Logo.svg" />
  </div>
      <img id="insta-glow" src="media/instagram-glow.svg" />
  <div class="content-container">
    <p class="sub-paragraph">Search Hashtag</p>
    <form>
      <input id="hashtagInput" />
      <input type="submit" id="addHashtag" id="grabHashtag" value="Submit Hashtag" />
    </form>
    <div class="divider"></div>
        <p>You have liked <span id="count">0</span> photographs</p>
  <form id="start-auto-form">
    <input type="submit" id="start-auto" value="Start Automation" />
  </form>
  </div>


  <script src="inject.js"></script>
  <script src="popup.js"></script>
</body>

</html>

inject.js

    /******************************
    # Inject into URL on submit
    ******************************/
    document.querySelector('#start-auto').addEventListener("click", findUrl);

    function findUrl() {
      console.log(userHash)
      let hashtagUrl = window.open("https://www.instagram.com/explore/tags/" + userHash );
//*This is the area I am trying to push the array to
    }

/*******************************************
# Inject addHashtag array into URL on submit
********************************************/
document.querySelector('#addHashtag').addEventListener("click", addHashtag);

function addHashtag() {
  chrome.runtime.sendMessage(hashtagInput.value);
}

background.js

/******************************
# Inject likebot into page
******************************/
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {

  chrome.tabs.executeScript(tabId, {
    file: 'likeBot.js'
  }, _ => chrome.runtime.lastError /* "check" error */ )

});

/************************************************************
# Recieve message from likeBot.js and send it to popup.html
************************************************************/
let updateCount = document.getElementById('count');

chrome.runtime.onMessage.addListener(function(response, sender, sendResponse) {
  if (updateCount) {
    updateCount.innerHTML = response;
  }
  chrome.storage.sync.set({
    'value': response
  });
});

/************************************************************
# Recieve message from likeBot
************************************************************/
if (updateCount) {
  chrome.storage.sync.get('value', function(data) {
    updateCount.innerHTML = data.value;
  });
}

/************************************************************
# Grab and store hashtag from input field
************************************************************/
let hashtag = document.querySelector("#hashtagInput");
let userHash = [];

chrome.runtime.onMessage.addListener(function(hashtagInput, sender, sendResponse) {
  chrome.storage.sync.set({
        list:hashtagInput
    }, function() {
    });
  chrome.storage.sync.get({
      list:[] //put defaultvalues if any
  },
  function(data) {
     userHash.push(data.list);
     console.log('This is my array: ' + userHash);
     sendResponse(hashtagInput);
  }
  );
  sendResponse(userHash);
});

I will be up for another couple of hours trying to figure this out. I would appreciate any help someone could give me. The background.js script successfully creates an array from the user input, I just can't access it from my inject.js script.

Grant
  • 90
  • 1
  • 11

1 Answers1

1
  1. There are two onMessage listeners in the background script, so you need to combine them into one, otherwise only the first one will be able to send a response
  2. The extension API is asynchronous so the callback runs after the surrounding code has already finished, meaning sendResponse(hashtagInput) won't do anything. You should replace the subsequent sendResponse(userHash) with return true so onMessage will keep the channel open and replace sendResponse(hashtagInput) with something that sends both variables in one object e.g. sendResponse({userHash, hashtagInput}) and of course the messaging caller should be changed to reflect that as well
  3. Currently all sendResponse are sending data into nothing because there's no callback parameter in sendMessage, see the messaging documentation for examples.
  4. The background script runs in a hidden separate background page, which is empty and not related to the browser action popup, so there'll be no DOM elements like #hashtagInput and updateCount will be null.
  5. The only thing you need in the background script is chrome.tabs.onUpdated listener so remove everything else.
  6. Write to the storage in the popup script
  7. Send a message to the tab in the popup script, for example:

    chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
      chrome.tabs.sendMessage(tab.id, {foo: 'bar'});
    });
    
  8. Use devtools to debug your code, inspect variables, set breakpoints, run line by line, which will eventually help you solve such simple problems really really quick.

Certainly, there will be more things you'll need to tweak before it all works out, for example it's unclear to me at this point why you're injecting likeBot into every tab that updates its title, audible state, favicon, loading state. Maybe you'll want to do it in popup.js to inject into the active tab only and thus there'll be no need for chrome.tabs.onUpdated and the background script altogether.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136
  • This is extremely helpful, thank you. This is my first real dev project so I am trying to learn as I go. I will mark this as the right answer and look into everything that you have stated. Especially how I can utilize chrome dev tools. – Grant Jan 21 '20 at 04:49