Search code examples
javascriptgoogle-chrome-extensionfetch-api

fetch() fails in Chrome extension under Windows but not MacOS


Introduction (added in edit):I am working on a Chrome extension that I want to be able to communicate with a server using fetch(). When I included such a feature in the new version of the extension, I noticed that only a very small fraction of the users recorded by the Chrome Web Store stats actually had made contact with the server, although that should happen automatically when the extension loads (my server script logs the requests). Therefore there seems to be some difference between different instances of the extension, maybe due to different OSes, in the capacity to perform the fetch() command.

Question: I have created a minimalistic demo extension below which contains the fetch() step. Basically, the server returns the date and time in PHP "U" format (seconds since Jan 1, 1970) and the extension then logs this data to the console. Using this on the Mac on which I developed the extension, it works fine. The fetch() line also works when entered in the devtools console, as long as the web page used has the same origin as the server script.

However, when I use the demo extension in a Windows environment, I get the error message "Uncaught (in promise) TypeError: Failed to fetch". In contrast, pasting the fetch() command into the console works and returns the server response, just as on the Mac. Is this a known issue with Chrome extensions, fetch() and Windows?

For testing the extension (can be downloaded from https://oldpike.bxtrom.eu/mentiplus/demo_ext.zip), navigate to https://mentimeter.com (I matched this site as it is my target in the original extension – you can enter another site in the manifest if you like). For testing the command in the devtools console, navigate to https://oldpike.bxtrom.eu/mentiplus/demo-list.txt

Mac: OS 12.4; Chrome 102.0.5005.61
Windows: OS 7 professional (emulated in Parallels Desktop 17.1.4 on my Mac); Chrome 102.0.5005.115 (Official Build) (64-bit)

Demo extension

manifest.json

{
  "manifest_version": 3, 
  "name": "demo_ext",
  "version": "0.1",
  "description": "demo",
  
  "background": {
        "service_worker": "background.js"
      },    
"host_permissions":["https://oldpike.bxtrom.eu/mentiplus/*"],
 "content_scripts": [{
      "js": ["content.js"],
    "matches": ["https://www.mentimeter.com/*"]
  }],
 
  "web_accessible_resources":[{"resources":[],
  "matches":["https://www.mentimeter.com/*"]}]
}

background.js

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
    switch(request.command){
       case "runDemo":
        fetch("https://oldpike.bxtrom.eu/mentiplus/phptest.php").then(response => response.text()).then(data => sendResponse(data));
       break;
     };
    return true;
});

content.js

chrome.runtime.sendMessage({ command: "runDemo" }, function (response) {
  console.log("demo data: " + response);
})

server script

<?php
  $id = date("U");
  echo $id;
?>

command in console

fetch("https://oldpike.bxtrom.eu/mentiplus/phptest.php").then(response => response.text()).then(data => console.log(data));

Solution

  • What jumps out to me in your setup is Win 7.

    I looked at your site with a TLS test suite, it's using Letsencrypt - you should be aware that due to their chain of trust change, older OSes (especially if not fully updated, which can be an issue in a spun-up-for-quick-test VM) may trip on trusting the certificate.

    You can test if that is the problem by opening https://valid-isrgrootx1.letsencrypt.org/ in your VM's Chrome and seeing if it is blocked as insecure.

    If that is the case, you can work around the issue by adding the new ISRG X1 root certificate (self-signed) to your OS trust store from https://letsencrypt.org/certificates/

    P.S. You can also quicky check if this is the issue by using non-HTTPS URL http://oldpike.bxtrom.eu/mentiplus/phptest.php for a quick test.