Where can I properly use the API "chrome.downloads" when I want to download?

Ⅰ. Introduction

I have read a lot and tried various ways of using the chrome.downloads API. But until now, I am still helpless in finding a way to use the chrome.downloads API.

Instructions from the docs didn't seem to help me much. So I decided to come here to ask and present to everyone about the problem that I am facing. I hope it helps many people.

My project uses manifest version 3.

Here is the GitHub link of the project: https://github.com/ATU8020/Use-API-chrome.downloads.git

Ⅱ. Presenting the Problem

Some related concepts are used:

  1. Service worker
  2. Content script
  3. Asynchronous function
  4. Synchronous function

Problems

I know that service workers require asynchronous function.

Listeners must be registered synchronously from the start of the page. LINK

Do not register listeners asynchronously, as they will not be properly triggered. LINK

But the chrome.downloads.download API returns a Promise:

API Chrome.downloads

See chrome.downloads docs.

That confused me. I have also tried other ways, such as with the content script. But after reading the docs, I know that the API chrome.downloads cannot be used directly. enter image description here

See content script docs.

Comment

That is the crux of my question. Any constructive comments and useful information are always appreciated.

Ⅲ. More Information

If using the API chrome.downloads in file popup.js it works; what does that mean?

I know that could be an alternative solution.

But what if you want to do something like download when you click on a contextMenu? Is it possible?

enter image description here


The fact that the method returns a Promise is not related to the way the listeners are registered.
You can call asynchronous code inside the listener in the background script.

  • ignoring the result:

    chrome.contextMenus.onClicked.addListener(info => {
      chrome.downloads.download({url: info.linkUrl});
    });
    
  • using the result:

    chrome.contextMenus.onClicked.addListener(async info => {
      const downloadId = await chrome.downloads.download({url: info.linkUrl});
      console.log('downloadId:', downloadId);
    });
    

    Beware: chrome.runtime.onMessage listener doesn't work with async functions yet, more info.