From 31a346fcf2a05232643bd2ce6b869aa91042a045 Mon Sep 17 00:00:00 2001 From: Peter Holmberg Date: Wed, 23 Oct 2019 10:30:31 +0200 Subject: [PATCH] Core: Show browser not supported notification (#19904) * display appEvent on load * move to app.ts, create util and tests * adding case for ie edge * Updated browser notice text --- public/app/app.ts | 14 ++++- public/app/core/utils/browser.test.ts | 74 +++++++++++++++++++++++++++ public/app/core/utils/browser.ts | 31 +++++++++++ 3 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 public/app/core/utils/browser.test.ts create mode 100644 public/app/core/utils/browser.ts diff --git a/public/app/app.ts b/public/app/app.ts index 725ef075ac3..3016f41167c 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -18,7 +18,10 @@ import angular from 'angular'; import config from 'app/core/config'; // @ts-ignore ignoring this for now, otherwise we would have to extend _ interface with move import _ from 'lodash'; +import { AppEvents, setMarkdownOptions, setLocale } from '@grafana/data'; +import appEvents from 'app/core/app_events'; import { addClassIfNoOverlayScrollbar } from 'app/core/utils/scrollbar'; +import { checkBrowserCompatibility } from 'app/core/utils/browser'; import { importPluginModule } from 'app/features/plugins/plugin_loader'; // add move to lodash for backward compatabiltiy @@ -34,8 +37,6 @@ import { setupAngularRoutes } from 'app/routes/routes'; import 'app/routes/GrafanaCtrl'; import 'app/features/all'; -import { setLocale } from '@grafana/data'; -import { setMarkdownOptions } from '@grafana/data'; // import symlinked extensions const extensionsIndex = (require as any).context('.', true, /extensions\/index.ts/); @@ -146,6 +147,15 @@ export class GrafanaApp { }); this.preBootModules = null; + + if (!checkBrowserCompatibility()) { + setTimeout(() => { + appEvents.emit(AppEvents.alertWarning, [ + 'Your browser is not fully supported', + 'A newer browser version is recommended', + ]); + }, 1000); + } }); // Preload selected app plugins diff --git a/public/app/core/utils/browser.test.ts b/public/app/core/utils/browser.test.ts new file mode 100644 index 00000000000..4b8c8ac1d6c --- /dev/null +++ b/public/app/core/utils/browser.test.ts @@ -0,0 +1,74 @@ +import { checkBrowserCompatibility } from './browser'; + +const setUserAgentString = (userAgentString: string) => { + Object.defineProperty(window.navigator, 'userAgent', { + value: userAgentString, + configurable: true, + }); +}; + +const setVendor = (vendor: string) => { + Object.defineProperty(window.navigator, 'vendor', { + value: vendor, + configurable: true, + }); +}; + +describe('browser', () => { + describe('check compatibility', () => { + describe('Chrome', () => { + it('should be true for chrome version 77', () => { + setUserAgentString( + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36' + ); + setVendor('Google Inc.'); + + expect(checkBrowserCompatibility()).toBeTruthy(); + }); + + it('should be false for chrome version <= 54', () => { + setUserAgentString( + 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.71 Safari/537.36' + ); + setVendor('Google Inc.'); + + expect(checkBrowserCompatibility()).toBeFalsy(); + }); + }); + describe('IE', () => { + it('should be false for IE 11', () => { + setUserAgentString('Mozilla/5.0 (compatible, MSIE 11, Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko'); + setVendor('Microsoft'); + + expect(checkBrowserCompatibility()).toBeFalsy(); + }); + }); + describe('Edge', () => { + it('should be false for Edge <= 16', () => { + setUserAgentString( + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.79 Safari/537.36 Edge/14.14393' + ); + setVendor('Microsoft'); + + expect(checkBrowserCompatibility()).toBeFalsy(); + }); + + it('should be true for Edge version 44', () => { + setUserAgentString( + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36 Edg/44.18362.387.0' + ); + setVendor('Microsoft'); + + expect(checkBrowserCompatibility()).toBeTruthy(); + }); + }); + describe('Firefox', () => { + it('should be true for version 69', () => { + setUserAgentString('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/69.0'); + setVendor('Firefox'); + + expect(checkBrowserCompatibility()).toBeTruthy(); + }); + }); + }); +}); diff --git a/public/app/core/utils/browser.ts b/public/app/core/utils/browser.ts new file mode 100644 index 00000000000..a89bd6122f3 --- /dev/null +++ b/public/app/core/utils/browser.ts @@ -0,0 +1,31 @@ +// Check to see if browser is not supported by Grafana +export function checkBrowserCompatibility() { + const isIE = navigator.userAgent.indexOf('MSIE') > -1; + const isEdge = navigator.userAgent.indexOf('Edge/') > -1 || navigator.userAgent.indexOf('Edg/') > -1; + const isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; + const isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor); + + /* Check for + <= IE11 (Trident 7) + Edge <= 16 + Firefox <= 64 + Chrome <= 54 + */ + const isEdgeVersion = /Edge\/([0-9.]+)/.exec(navigator.userAgent); + + if (isIE && parseFloat(/Trident\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 7) { + return false; + } else if ( + isEdge && + ((isEdgeVersion && parseFloat(isEdgeVersion[1]) <= 16) || + parseFloat(/Edg\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 16) + ) { + return false; + } else if (isFirefox && parseFloat(/Firefox\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 64) { + return false; + } else if (isChrome && parseFloat(/Chrome\/([0-9.]+)/.exec(navigator.userAgent)[1]) <= 54) { + return false; + } + + return true; +}