How to determine in which browser your extension background script is executing?
C

4

13

I'm talking about Chrome extensions, Firefox WebExtensions, Edge extensions...

In a background script, not a content script, is there a clear way to know which browser I am using? I need to do different operations for different browsers.

Yes, navigator.userAgent can be useful, but it's not very clear.

Is there any extension API that can be used to do this? Something like, chrome.extension.browserType. (Of course, this one doesn't really exist..)

Crampton answered 24/1, 2017 at 2:59 Comment(0)
M
10

There is no specific API to detect which browser is currently being used. One of the benefits of the major browsers moving to support a common extension framework is being able to have a single codebase which supports multiple browsers. While the set of functionality which is available from all applicable browsers is growing, there will always be some differences. These differences are not just in what is supported, but in some cased are in the specifics of the effects for a particular API, or how the API must be used.1,2 Thus, for some things, it is necessary to be able to determine which browser the code is currently running.

There is some good code available from the top-voted answer to "How to detect Safari, Chrome, IE, Firefox and Opera browser?". However, it needs some modification to work in an extension environment.

Based on the code in that answer, the following will detect:

  • Chrome
  • Edge
  • Firefox
  • Opera
  • the Blink engine
// Opera 8.0+ (tested on Opera 42.0)
var isOpera = (!!window.opr && !!opr.addons) || !!window.opera 
                || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+ (tested on Firefox 45 - 53)
var isFirefox = typeof InstallTrigger !== 'undefined';

// Internet Explorer 6-11
//   Untested on IE (of course). Here because it shows some logic for isEdge.
var isIE = /*@cc_on!@*/false || !!document.documentMode;

// Edge 20+ (tested on Edge 38.14393.0.0)
var isEdge = !isIE && !!window.StyleMedia;

// Chrome 1+ (tested on Chrome 55.0.2883.87)
// This does not work in an extension:
//var isChrome = !!window.chrome && !!window.chrome.webstore;
// The other browsers are trying to be more like Chrome, so picking
// capabilities which are in Chrome, but not in others is a moving
// target.  Just default to Chrome if none of the others is detected.
var isChrome = !isOpera && !isFirefox && !isIE && !isEdge;

// Blink engine detection (tested on Chrome 55.0.2883.87 and Opera 42.0)
var isBlink = (isChrome || isOpera) && !!window.CSS;

/* The above code is based on code from: https://mcmap.net/q/42092/-how-to-detect-safari-chrome-ie-firefox-and-opera-browsers */    
//Verification:
var log = console.log;
if(isEdge) log = alert; //Edge console.log() does not work, but alert() does.
log('isChrome: ' + isChrome);
log('isEdge: ' + isEdge);
log('isFirefox: ' + isFirefox);
log('isIE: ' + isIE);
log('isOpera: ' + isOpera);
log('isBlink: ' + isBlink);

  1. Different implementations of an API which interfaces with something as complex and diverse as the different browsers will always end up with, at least, subtle differences between implementations. Currently, many of the differences are not that subtle.
  2. Mozilla has explicitly stated that they intend to implement functionality for WebExtensions which is not currently available in other browsers by extending the chrome.*/browser.* APIs. One way that this is being done is that there is a mechanism called WebExtensions Experiments which is intended for non-Mozilla developers to implement additional functionality for WebExtensions. The intent is that such functionality, if approved, will be migrated into stock Firefox builds.
Matzo answered 24/1, 2017 at 5:33 Comment(2)
There is also the runtime.getBrowserInfo() API, but at the moment it is only supported by Firefox.Salter
window.StyleMedia is undefined in Edge v108.0.1462.41Substation
T
1

Here's another technique. The browser.identity.getRedirectUrl function will return a URL post-fixed with:

  • .extensions.allizom.org/ when running from Firefox
  • .chromiumapp.org/ when running from Chrome/Chromium

It's simple enough to call this upon startup and store it in the runtime state of your background script. Edge and Opera also support this function.

Now usually Web Extension API calls start with chrome when running in Chrome, but by this point cross-browser extension writers should be used to the Web Extension Polyfill JS, and you'll need to use this too if you want the call to browser.identity.getRedirectUrl to work on any browser.

Trapeziform answered 18/1, 2022 at 19:57 Comment(1)
Will not work for safari. Actaully you there is no identity in safari so you need to use the sendMessage.Ross
A
1

It's best choice, but for now only work at Firefox.

browser.runtime.getBrowserInfo()
Anthropology answered 14/8, 2022 at 16:37 Comment(0)
F
0

Add a constant to hold the value. Modify what it is set for before publishing to each browser store.

I.E:

const BrowserCode = {
    CHROME:1,
    FF: 2,
};

// to submit to chrome
const CURRENT_BROWSER = BrowserCode.CHROME;

// or to submit to FF
const CURRENT_BROWSER = BrowserCode.FF;

// elsewhere

if (CURRENT_BROWSER === BrowserCode.CHROME) {

}

//or

const behavior = {
    BrowserCode.CHROME: () => {},
    BrowserCode.FIREFOX: () => {}
}

behavior[CURRENT_BROWSER]();

To perform the setup, you can just have some simple shell script to perform string substitution. In this case, you could have one browser type be BrowserCode.UNDEFINED. In such case, you would just need a regex to find the line that starts with const CURRENT_BROWSER and ends with BrowserCode.UNDEFINED; and sub it for the correct one.

Floccose answered 28/3, 2023 at 1:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.