0

I can find plenty of questions for sending a message from Bbackground to content scripts or from popup to background scripts, but I can't find any on how to send a message from options.js (triggered from my options page) to background.js for my Chrome extension

manifest.js

{
  ...
  "manifest_version": 3,
  "permissions": [
    "alarms",
    "contextMenus",
    "notifications",
    "storage"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  },
  "options_page": "options.html",
  "icons": {
    "48": "/assets/icons/icon-48.png",
    "128": "/assets/icons/icon-128.png"
  }
}

Code in options.js

// Save options
document.querySelector('#save').addEventListener('click', ()=> {
  // Check for selected regions
  let selectedRegions = [];
  regionChecks.forEach(elm => {
    if (elm.checked)
      selectedRegions.push(elm.id.replace('region-', ''))
  });
  // Save selections
  chrome.storage.sync.set({ 'regions': selectedRegions });

  // Check for refresh period
  let refreshPeriod = document.querySelector('#refresh');
  if (refreshPeriod) {
    refreshPeriod = parseInt(refreshPeriod.value);
    if (refreshPeriod === NaN) {
      refreshPeriod = 5;
    } else if(refreshPeriod < 2) {
      refreshPeriod = 2;
    } else if (refreshPeriod > 120) {
      refreshPeriod = 120;
    }
    // Save period
    chrome.storage.sync.set({ 'refresh': refreshPeriod });
  }

  // Loop through features and remove if region gone
  chrome.storage.local.get(['features'], featuresData => {
    let featureCount = 0;
    if (featuresData.features) {
      featureSet = featuresData.features;
      Object.keys(featureSet).forEach(key => {
        if (!selectedRegions.includes(featureSet[key].Region)) {
          delete featureSet[key];
        } else if (featureSet[key].Status !== "read") {
          featureCount = featureCount + 1;
        }
      });
      // Update features data
      chrome.storage.local.set({ 'features': featureSet });
      // Update the badge
      if (featureCount > 0) {
        chrome.action.setBadgeText({ text: featureCount.toString() });
      } else {
        chrome.action.setBadgeText({ text: '' });
      }
    }
  });

  // Trigger an update
  chrome.runtime.sendMessage('', {
    type: 'update'
  });

  // Close the options page
  close();
});

Code in background.js

// Listen for messages
chrome.runtime.onMessage.addListener(data => {
  console.log(data);
  if (data.type === 'update') {
    scheduleRequest();
  }
});

But nothing is happening

I've tried using tabs.sendMessage, but even if I put tabs in permissions it tells me that it isn't defined when I add it to the function chrome.tabs.sendMessage(tabs[0].id, {...

dpDesignz
  • 1,909
  • 10
  • 34
  • 70
  • 1) Remove `'',` from sendMessage. 2) [How to see background.js console?](/a/10258029), 3) Maybe move `close()` into the callback of sendMessage. – wOxxOm Dec 01 '22 at 09:15
  • @wOxxOm thanks, this did it! :D If you want to post 1 and 3 as an answer I'll accept it – dpDesignz Dec 02 '22 at 01:34

2 Answers2

0

My test results contradict your claim.

enter image description here

manifest.json

{
  "manifest_version": 3,
  "name": "hoge",
  "version": "1.0",
  "background": {
    "service_worker": "background.js"
  },
  "options_page": "options.html"
}

background.js

// Listen for messages
chrome.runtime.onMessage.addListener(data => {
  console.log(data);
  if (data.type === 'update') {
    console.log("hoge")
    //    scheduleRequest();
  }
});

options.js

// Trigger an update
chrome.runtime.sendMessage('', {
  type: 'update'
});

options.html

<html>
<body>
  options page
  <script src="options.js"></script>
</body>
</html>
Norio Yamamoto
  • 1,495
  • 2
  • 3
  • 10
  • Sorry, I just realised I forgot something vital in my `options.js` file example. That code is only running after I click save. I've just tested my code again and it's not showing a console still. – dpDesignz Dec 01 '22 at 00:44
  • I think you should post all files. – Norio Yamamoto Dec 01 '22 at 00:54
  • Prove that chrome.runtime.sendMessage in options.js is called. – Norio Yamamoto Dec 01 '22 at 01:14
  • I've posted my full code in that function. Everything else in that function is working just fine, it's just not triggering anything in my `background.js`. Everything else in my `background.js` file is also running with no problems. I just seem to be having an issue with the `sendMessage` – dpDesignz Dec 01 '22 at 02:26
  • Set a breakpoint on the line calling chrome.runtime.sendMessage() in options.js and make sure it breaks. – Norio Yamamoto Dec 01 '22 at 03:36
0

After some input from @woxxom and @Norio, and a little bit more troubleshooting, this is how I managed to get it to work

option.js:

// Trigger an update
chrome.runtime.sendMessage({ type: 'update' }, result => {
  // Close the options page
  close();
});

I had to move the close(); event into the return function so it didn't prematurely close off the code. I also had to have a paramter in the return function for some reason otherwise it wouldn't run with an empty arrow function.

background.js:

// Listen for messages
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'update') {
    startRequest(true).then(sendResponse);
    return true;
  }
});

My function to be triggered in the background.js file was already an async promise function, so I had to add a .then() for the onMessage response function to trigger once it had run. It also wouldn't work without having return true; in there.

dpDesignz
  • 1,909
  • 10
  • 34
  • 70