Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

browser.runtime.sendMessage returns undefined on Firefox #172

Closed
astronaute77 opened this issue Jan 24, 2019 · 11 comments
Closed

browser.runtime.sendMessage returns undefined on Firefox #172

astronaute77 opened this issue Jan 24, 2019 · 11 comments

Comments

@astronaute77
Copy link

astronaute77 commented Jan 24, 2019

Using Angular 7, the generated example is attached.

Not sure if I'm doing something wrong as it seems pretty straightforward bug to catch.

Popup:

handleResponse(msg) {
    console.log("handleResponse", msg);
}

browser.runtime.sendMessage("test").then(this.handleResponse);

Background:

browser.runtime.onMessage.addListener(() =>{
    return new Promise(resolve => {
      setTimeout(() => {
        resolve("async response from background script");
      }, 2000);
      });
    });

test_ff_promise_bug.zip

On Chrome, the console shows "async response from background script" after 2s as expected.
On Firefox, it shows immediately "undefined".

@Rob--W
Copy link
Member

Rob--W commented Jan 24, 2019

Can you provide a full example that demonstrates your issue?

@astronaute77
Copy link
Author

Can you provide a full example that demonstrates your issue?

In an isolated extension the issue doesn't exist.
It must be something related to Angular 7 I'm using to develop the extension.

It will be a long night :) (closing this issue)

@rpl
Copy link
Member

rpl commented Jan 24, 2019

@astronaute77 As briefly mentioned in the readme included in this repo (https://github.com/mozilla/webextension-polyfill#issues-that-happen-only-when-running-on-firefox), the polyfill is actually a no-op when the extension runs on Firefox.

In this particular case, I suspect that the issue triggered by your extension may be the one described in #105: if the extension is using a Promise polyfill instead of the Firefox native one, the WebExtensions internals will not treat the promises created by the Promise polyfill as real promises.

This issue (and how to fix it) is described by @Rob--W in #105 (comment), and one of the possible workaround for that issue is described in #105 (comment).

Hopefully the comments linked above may help you to "make the debugging night a bit shorter" ;-)

Best,
Luca

@astronaute77
Copy link
Author

@rpl I'm using firefox-webext-browser (https://www.npmjs.com/package/@types/firefox-webext-browser).

It is probably related to the issue at hand.

I'm still trying to resolve it, will keep you updated.

@astronaute77
Copy link
Author

astronaute77 commented Jan 24, 2019

test_ff_promise_bug.zip

OK well I tried a lot of different things in order to pinpoint the issue to no avail. I would appreciate if someone more knowledgable could take a look.
I provided the smallest possible extension generated using Angular 7.

I can also provide source code if needed.

I'm using webextension-polyfill obviously, as well as DefinitelyTyped firefox-webext-browser (because firefox uses almost exact standard webext notation)

ping @rpl :)

@rpl
Copy link
Member

rpl commented Jan 24, 2019

@astronaute77 from a quick look to the zip file (in particular to the file named polyfills.js) it seems that the native Promise constructor is likely being redefined by angular's Zone.js and set to a custom ZoneAwarePromise constructor.

Unfortunately I don't know enough about Angular and its Zone.js part to be able to quickly determine if there is an easy and reasonable workaround to prevent Angular from redefining the Promise constructor (or if Angular can still be used without using Zone.js).

@astronaute77
Copy link
Author

@astronaute77 from a quick look to the zip file (in particular to the file named polyfills.js) it seems that the native Promise constructor is likely being redefined by angular's Zone.js and set to a custom ZoneAwarePromise constructor.

Unfortunately I don't know enough about Angular and its Zone.js part to be able to quickly determine if there is an easy and reasonable workaround to prevent Angular from redefining the Promise constructor (or if Angular can still be used without using Zone.js).

@rpl If I understand you correctly, there is zero chance of this working with ZoneAwarePromise? It absolutely has to be vanilla Promise?

@rpl
Copy link
Member

rpl commented Jan 24, 2019

@rpl If I understand you correctly, there is zero chance of this working with ZoneAwarePromise? It absolutely has to be vanilla Promise?

@astronaute77 yes, Firefox requires that the promise returned by runtime.onMessage listener to be a native Promise.

Looking at the code you pasted in the issue description, one option that may work for your extension is to send the asynchronous response by using the sendResponse callback instead of returning the non-native Promise, e.g. something like:

browser.runtime.onMessage.addListener((msg, sender, sendResponse) =>{
   setTimeout(() => {
      // calling sendResponse to asynchronously sending a response to the sender.
      sendResponse("async response from background script");
    }, 2000);
   
   // Tells Firefox (or the webextension-polyfill when running on chrome) that this listener
   // is going to reply asynchronously. 
   return true;
 });

@astronaute77
Copy link
Author

@rpl If I understand you correctly, there is zero chance of this working with ZoneAwarePromise? It absolutely has to be vanilla Promise?

@astronaute77 yes, Firefox requires that the promise returned by runtime.onMessage listener to be a native Promise.

Looking at the code you pasted in the issue description, one option that may work for your extension is to send the asynchronous response by using the sendResponse callback instead of returning the non-native Promise, e.g. something like:

browser.runtime.onMessage.addListener((msg, sender, sendResponse) =>{
   setTimeout(() => {
      // calling sendResponse to asynchronously sending a response to the sender.
      sendResponse("async response from background script");
    }, 2000);
   
   // Tells Firefox (or the webextension-polyfill when running on chrome) that this listener
   // is going to reply asynchronously. 
   return true;
 });

sendResponse is deprecated as per the documentation, this is why I'm trying to use the recommended implementation.

But you already know that :)
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage

Should I open an issue in Zone JS github?

@PedroS11
Copy link

PedroS11 commented Apr 7, 2022

I created an extension with react-creat-app and I'm struggling with the same problem. The onMessage listener is returning a string but it's never received on the sendMessage call, is there any solution for it? As far as I know, create-react-app uses the native Promises

linonetwo added a commit to tiddly-gittly/Browser-Extension-Tiddlywiki-Collector that referenced this issue Oct 12, 2023
@linonetwo
Copy link

linonetwo commented Oct 12, 2023

Just return the response, instead of sendResponse. See my commit above ↑

This might be a bug of polyfill, maybe you should reopen this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants