1

The issue:

I have a chrome extension that fetches some data when the user clicks a hotkey. The fetch happens in the background. However, if you open and close the popup, the fetch for that request never returns. I can see it go out in the network requests, but it just sits as pending. If you don't open and close the popup, it returns just fine.

Here are the relevant files/code:

Manifest file:

{
  "manifest_version": 3,
  "name": "Simple hotkey extension",
  "version": "0.0.1",
  "description": "Extension",
  "icons": {
    "16": "icon.png",
    "48": "icon.png",
    "128": "icon.png"
  },
  "action": {
    "default_icon": {
      "16": "icon.png",
      "24": "icon.png",
      "32": "icon.png"
    },
    "default_title": "Title",
    "default_popup": "popup/popup.html"
  },
  "host_permissions": ["<all_urls>"],
  "options_page": "options.html",
  "permissions": [
    "activeTab",
    "contentSettings",
    "contextMenus",
    "scripting",
    "storage",
    "unlimitedStorage"
  ],
  "background": {
    "persistent": true,
    "service_worker": "background.js"
  }
}

Relevant part of background:

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
  if (request.message === 'SEND_URL_DETAIL') {
    const {url, website} = request;
    fetchPageData(url, website)
      .then(data => {
        console.log(data, 'this is my data');
        appendStoredClicks(data);
      })
      .catch(err => console.log(err));
    // It's unclear if Chrome extension development actually needs a response.
    sendResponse({farewell: 'goodbye'});
  }
});

The API request from the utils folder:

export async function fetchPageData(
  url: string,
  website: string,
): Promise<any> {
  
  const wrappedUrl = `http://localhost:8080/fetch/website?url=${url}&website=${website}`;

  console.log('About to fetch');

  const res = await fetch(wrappedUrl);
  if (!res.ok) {
    throw new Error('Page not found');
  }
  const data = await res.json();

  console.log('Data received', data);

  return {...data, url};
}

Update based on @wOxxOm's comment I use react so popup.html is compiled by npm. Here's the current output.

Popup.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hotkey Extension</title>
  <meta name="viewport" content="width=device-width, initial-scale=1"></head>
  <body>
  <script src="popup.js"></script>
</body>
</html>

These are the only places where I can see onMessage called. enter image description here

Popup.js only has 3 lines of code that use Chrome:

  • chrome.action.setBadgeText
  • chrome.storage.onChanged.addListener(listener);
 - chrome.tabs.query(

      {
        active: true,
        currentWindow: true,
      },
      tabs => {
        chrome.tabs.sendMessage(tabs[0].id, {
          msg: Messages.DELETE_STUFF,
        });

Would any of these cause the problem?


Why does closing the chrome extension popup prevent these from returning and make the service worker inactive? It seems like such a weird behavior. How do I make them persist and not lose the response.

dizzy
  • 1,177
  • 2
  • 12
  • 34
  • The popup runs only when shown, it's terminated when closed. – wOxxOm May 18 '22 at 04:32
  • @wOxxOm, yup, but I don't do anything in the popup other than show the data from storage. I do all of this within the background/service worker. That's why it's so weird. --> Here's the scenario. I'm on a web page (content script) and hit a hot key. It sends a message to the background that reaches out an a remote API to grab some data. If during that request/response I happen to open/close the popup, it breaks the request. The service worker goes inactive and the response never comes back. If I don't open/close the popup - the response comes back just fine. – dizzy May 18 '22 at 05:41
  • Your popup script probably has onMessage listener or you mistakenly load background.js in popup.html. – wOxxOm May 18 '22 at 06:10
  • @wOxxOm I've added all the relevant pieces to the code above. Let me know if that helps! I don't see an onMessage listener or background.js being in popup.html. – dizzy May 18 '22 at 07:02
  • Sounds like a bug in Chrome, but there's also a problem in your manifest.json: the localhost permission must be in `host_permissions` not in `permissions`. – wOxxOm May 18 '22 at 07:11
  • @wOxxOm Was hoping that wasn't the case :( I've updated the manifest file for . Good catch. – dizzy May 18 '22 at 07:31
  • Submitted a bug - https://bugs.chromium.org/p/chromium/issues/detail?id=1326804 – dizzy May 18 '22 at 07:52
  • Add a zipped extension for them to test easily. – wOxxOm May 18 '22 at 10:24
  • @wOxxOm will do. Trouble is finding the right remote API fetch that takes long enough to cause the issue. Anything 5+ seconds gives you the time to open/close the popup and recreate the issue. By the way, I used a version of your keepalive solution here and now they don't drop even when opening/closing the popup https://stackoverflow.com/questions/66618136/persistent-service-worker-in-chrome-extension – dizzy May 18 '22 at 18:46
  • @wOxxOm noticed your comment in the SO answer above about always doing a "sendresponse" when using sendmessage. 'm not sure what bug you were referencing in that thread, but I actually don't do that in my contentscript when communicating with background. Think that would cause the problem? – dizzy May 18 '22 at 18:53

0 Answers0