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

Compatibility with environments that have the `browser` namespace but don't support promises #3

Closed
snoack opened this issue Oct 21, 2016 · 29 comments

Comments

@snoack
Copy link

@snoack snoack commented Oct 21, 2016

This polyfill seems to be incompatible with Microsoft Edge, which doesn't support promises yet, but is using the browser instead of the chrome namespace.

@snoack snoack changed the title Compatibility with environments that have the `browser` namespace but don't support promises Compatibility with environments that have the `browser` namespace but don't support promises (i.e. Microsoft Edge) Oct 21, 2016
@snoack snoack changed the title Compatibility with environments that have the `browser` namespace but don't support promises (i.e. Microsoft Edge) Compatibility with environments that have the `browser` namespace but don't support promises Oct 21, 2016
@kmaglione
Copy link
Collaborator

@kmaglione kmaglione commented Nov 6, 2016

Edge is planning to add promise support, but yes, I've been thinking about ways to detect this and add support where it's not available.

@snoack
Copy link
Author

@snoack snoack commented Nov 9, 2016

Well, I presume it will still take a while until Microsoft Edge will support promises, and when it does extension developers might not be able to drop support for older versions of Microsoft Edge right away. Also what if Chrome (or a new platform) will start to provide the browser namespace but doesn't support promises in the same step.

As for detecting the promise-based API, the best idea I have is just calling any asynchronous function and check whether it throws an exception (because a callback is expected) or whether a promise is returned.

if (typeof browser == "undefined")
  var browser = chrome;

var _supportsPromises = false;
try {
  _supportsPromises = browser.runtime.getPlatformInfo() instanceof Promise;
}
catch (e)
{
}

if (!_supportsPromises)
  browser = wrapAPI(browser);
@DaAwesomeP
Copy link

@DaAwesomeP DaAwesomeP commented Apr 16, 2017

Here's the issue on the Microsoft end: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9421085/. Maybe they'll post an update if a decent amount of people click the "Me too" button.

@myfreeweb
Copy link

@myfreeweb myfreeweb commented Apr 22, 2017

Changed Status from “Confirmed” to “By design”

:(

@DaAwesomeP
Copy link

@DaAwesomeP DaAwesomeP commented Apr 26, 2017

James M. Apr 24, 2017 Microsoft Edge Team

Hello,

Thank you for providing this information about the issue. A Microsoft Edge Extension does not support the Promise model; this is a documented difference between Mozilla and Edge’s platform. Currently, we do not plan to release a fix. Please update this case if you can provide new information for us to consider.

Best Wishes,
The MS Edge Team

https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9421085/

@myfreeweb
Copy link

@myfreeweb myfreeweb commented Apr 30, 2017

Considering Microsoft's track record of not following standards and their somewhat recent desire to not be like that anymore, it's really weird that they're so dismissive about this…

I guess supporting this in the polyfill would be the only solution for now :(

@Noitidart
Copy link

@Noitidart Noitidart commented Apr 30, 2017

Ideally I would like to use this polyfill but due to edge I was using this really short polyfill and it was working well:

@constfun I find this works for me across all browsers including edge:

const deepAccessUsingString = (obj, dotpath) => dotpath.split('.').reduce((nested, key) => nested[key], obj);

window.extension = typeof chrome !== 'undefined' && chrome.runtime ? chrome : browser;
window.extensiona = function(dotpath, ...args) {
    let basepath = dotpath.split('.');
    basepath.pop();
    basepath = basepath.join('.');
    return new Promise(resolve => deepAccessUsingString(TRUNK, dotpath)(...args, resolve));
}

Usage example:

/* USAGE - sync apis */
extension.browserAction.onClicked.addListener(handleClick);
extension.tabs.create({ url:'blah' }); // if dont care about return
extension.browserAction.setTitle({ title:'rawr' })

/* USAGE - async/callback based api's are as promise */
async function() {
    const info = await extensiona('runtime.getPlatformInfo');
    const tabInfo = await extensiona('tabs.create', { url:'blah' });
    const download = await extensiona('downloads.download', { filename:`filename.here`, url:`www.bing.com/blah` });
    const winId = await extensiona('windows.update', windowid, { focused:true });
}

The only issue i see is in extensiona (the promise version), using deepAccessUsingString might disconnect the api call from the the this. I haven't had issues with it yet though.

To use this, just do extension.** instead of browser.* or chrome.*. If you want callback version.

Edge is also funky in that they have window.chrome, so that's a not good enough test, that's why I test window.chrome.runtime above to see if chrome trunk exists.

@fregante
Copy link
Contributor

@fregante fregante commented Aug 20, 2017

What a sad state of affairs. It looks like Chrome doesn't care about Mozilla's WebExtensions standardization effort and Edge just (barely) follows whatever Chrome does. On top of that, Chrome's original API is pretty ridiculous to begin with.

At this point I wish mozilla came up with a sound API and polyfilled that.

@myfreeweb
Copy link

@myfreeweb myfreeweb commented Aug 20, 2017

@bfred-it uhh this repo is exactly the polyfill :)

@fregante
Copy link
Contributor

@fregante fregante commented Aug 20, 2017

Yeah but mozilla's API still looks like browser.runtime.onBrowserUpdateAvailable.addListener(fn)

It could have looked more like a familiar browser.runtime.on('BrowserUpdateAvailable', fn)

@myfreeweb
Copy link

@myfreeweb myfreeweb commented Aug 20, 2017

that's pretty minor compared to using promises instead of callbacks

@osdiab
Copy link

@osdiab osdiab commented Aug 22, 2017

Aw man, just began working on a Web Extension and ran into this. Hope this can be prioritized soon / maybe I'll try to take a jab at it at some point.

@myfreeweb
Copy link

@myfreeweb myfreeweb commented Aug 22, 2017

@osdiab look at #43 which was mentioned here

@constfun
Copy link

@constfun constfun commented Oct 10, 2017

At the moment, neither a working polyfill, nor any other cross browser solution exists.
An unfortunate state of affairs, but we people of the web are used to this by now.

May I suggest some possible improvements:

  1. Address idiosyncrasies of each browser vendor explicitly, based on the user agent, instead of the current approach.
  2. Instead of polyfilling globals, export an object with Mozilla's version of the API.

On point 1, I argue that it is more robust and simpler than attempting non-trivial feature detection, as in #43. The set of browsers currently supporting WebExtensions is known and the chances of your extension working in some other incarnation of the API without being explicitly targeted is slim.

On point 2, an anecdote.

I just had a fun time on a project that also uses pastak/chrome-browser-object-polyfill. That polyfill makes its own assumptions about the browser global. MetaMask/extensionizer makes different assumptions still.

A cross platform library is more useful to me as a developer than a polyfill that seals off all escape hatches by monkey patching globals.

@FranklinYu
Copy link

@FranklinYu FranklinYu commented Jan 8, 2018

The Edge issue has been re-opened by Edge team…

@Rob--W
Copy link
Member

@Rob--W Rob--W commented May 31, 2018

@rpl and I talked about this:

  • We want to support Edge, with minimal efforts (i.e. no large changes).
  • That is, a simple feature detection as shown in #3 (comment) (guarded on the existence of the Edge-specific msBrowser API).
  • The (existing) browser object will be replaced with the polyfilled one, which uses the global chrome object to implement the polyfill.
  • The polyfill should be tested (at least manually, ideally with continuous integration).
@NN---
Copy link

@NN--- NN--- commented Jun 17, 2018

@Rob--W Any estimations for including this functionality in webextension-polyfill ?

@ExE-Boss
Copy link
Contributor

@ExE-Boss ExE-Boss commented Jun 17, 2018

@NN--- I’ve been working on a fix in #114.

@vozeldr
Copy link

@vozeldr vozeldr commented Aug 20, 2018

Any ideas when this will be completed? I've seen multiple proposed pull requests and they always get shot down for some reason or another. It seems like a lot of "paralysis by over-analysis". It's been almost 2 years. Please implement something, even if it's temporary and not your ideal solution.

@Rob--W
Copy link
Member

@Rob--W Rob--W commented Aug 20, 2018

One of the big blockers is the ability to load an extension in Edge for automated testing (locally and on continuous integration, e.g. on AppVeyor).

If someone spends time on researching that, then I am willing to make the desired changes to the polyfill to support Edge.

@mjethani
Copy link

@mjethani mjethani commented Sep 22, 2018

In Adblock Plus we have written our own polyfill to wrap the async APIs on Chrome and Edge. It works for us.

@dessant
Copy link

@dessant dessant commented Sep 22, 2018

@Rob--W. the lack of automated testing isn't necessarily a blocker for releasing this feature.

@FranklinYu
Copy link

@FranklinYu FranklinYu commented Sep 22, 2018

@Rob--W Sadly AppVeyor won’t support Microsoft Edge testing. All tests on AppVeyor run on Windows Server 2012/2016, but MS Edge doesn’t support Windows Server at all. So far the only option that I know is BrowserStack, which has free plan for open-source projects, but I guess it would take some time to set up Selenium.

I think we Edge users would be happy enough if Edge is supported on a best-effort basis. We don’t need any guarantee about non-breaking release because we understand the difficulty.

@tophf
Copy link

@tophf tophf commented Dec 11, 2018

Soon Edge will use Chromium inside so it's reasonable to expect Edge will have the classic chrome API for extensions, which would solve the polyfill compatibility problem too.

@NN---
Copy link

@NN--- NN--- commented Dec 11, 2018

There are many companies using Edge right now.
It will take time for MS to release a Chromium based version and more time for companies to upgrade.

@FranklinYu
Copy link

@FranklinYu FranklinYu commented Dec 11, 2018

TBH Microsoft announced that too early. Now nobody would develop against the classic MS Edge no matter when the new Edge come out. This is not the only project; there is also some discussion at EFForg/https-everywhere#5101.

@NN---
Copy link

@NN--- NN--- commented Dec 11, 2018

Unfortunately, I do have to develop for current Edge.:(

@rpl rpl added the state: wontfix label Jan 7, 2019
@rpl
Copy link
Member

@rpl rpl commented Jan 7, 2019

Closing as wontfix. See #114 (comment) for a rationale.

@NN--- @vozeldr you may give a try to the alternative approach described in the above comment (and in the example-msedge-extension-with-webextension-polyfill github repo).

@rpl rpl closed this Jan 7, 2019
@NN---
Copy link

@NN--- NN--- commented Jan 7, 2019

I already do the same using Webpack and currently don't need any Edge specific features.
Just added window.chrome=window.browser prior running any extension code.
Anyway thanks for the sample, maybe I find it useful in the future.

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

Successfully merging a pull request may close this issue.

You can’t perform that action at this time.