diff --git a/.changeset/little-cycles-fold.md b/.changeset/little-cycles-fold.md new file mode 100644 index 00000000000..f3eb43dabf3 --- /dev/null +++ b/.changeset/little-cycles-fold.md @@ -0,0 +1,6 @@ +--- +"firebase": minor +"@firebase/performance": minor +--- + +Issue 2393 - Add environment check to Performance Module diff --git a/packages/performance/index.ts b/packages/performance/index.ts index b710243ff9b..6829a9154a1 100644 --- a/packages/performance/index.ts +++ b/packages/performance/index.ts @@ -26,7 +26,6 @@ import { ERROR_FACTORY, ErrorCode } from './src/utils/errors'; import { FirebasePerformance } from '@firebase/performance-types'; import { Component, ComponentType } from '@firebase/component'; import { FirebaseInstallations } from '@firebase/installations-types'; - import { name, version } from './package.json'; const DEFAULT_ENTRY_NAME = '[DEFAULT]'; diff --git a/packages/performance/src/controllers/perf.test.ts b/packages/performance/src/controllers/perf.test.ts index 1ff2f8b5c56..6d3a24e723f 100644 --- a/packages/performance/src/controllers/perf.test.ts +++ b/packages/performance/src/controllers/perf.test.ts @@ -22,6 +22,7 @@ import { Trace } from '../resources/trace'; import { Api, setupApi } from '../services/api_service'; import { FirebaseApp } from '@firebase/app-types'; import * as initializationService from '../services/initialization_service'; +import * as FirebaseUtil from '@firebase/util'; import { consoleLogger } from '../utils/console_logger'; import '../../test/setup'; @@ -46,11 +47,36 @@ describe('Firebase Performance Test', () => { it('does not initialize performance if the required apis are not available', () => { stub(Api.prototype, 'requiredApisAvailable').returns(false); stub(initializationService, 'getInitializationPromise'); - stub(consoleLogger, 'info'); new PerformanceController(fakeFirebaseApp); - expect(initializationService.getInitializationPromise).not.be.called; - expect(consoleLogger.info).be.called; + }); + it('does not initialize performance if validateIndexedDBOpenable return false', async () => { + stub(Api.prototype, 'requiredApisAvailable').returns(true); + const validateStub = stub( + FirebaseUtil, + 'validateIndexedDBOpenable' + ).resolves(false); + stub(initializationService, 'getInitializationPromise'); + new PerformanceController(fakeFirebaseApp); + await validateStub; + expect(initializationService.getInitializationPromise).not.be.called; + }); + + it('does not initialize performance if validateIndexedDBOpenable throws an error', async () => { + stub(Api.prototype, 'requiredApisAvailable').returns(true); + const validateStub = stub( + FirebaseUtil, + 'validateIndexedDBOpenable' + ).rejects(); + + stub(initializationService, 'getInitializationPromise'); + stub(consoleLogger, 'info'); + new PerformanceController(fakeFirebaseApp); + try { + await validateStub; + expect(initializationService.getInitializationPromise).not.be.called; + expect(consoleLogger.info).be.called; + } catch (ignored) {} }); }); diff --git a/packages/performance/src/controllers/perf.ts b/packages/performance/src/controllers/perf.ts index 47cd478807d..9793f614dd4 100644 --- a/packages/performance/src/controllers/perf.ts +++ b/packages/performance/src/controllers/perf.ts @@ -21,18 +21,25 @@ import { getInitializationPromise } from '../services/initialization_service'; import { Api } from '../services/api_service'; import { FirebaseApp } from '@firebase/app-types'; import { FirebasePerformance } from '@firebase/performance-types'; -import { consoleLogger } from '../utils/console_logger'; import { setupTransportService } from '../services/transport_service'; - +import { validateIndexedDBOpenable } from '@firebase/util'; +import { consoleLogger } from '../utils/console_logger'; export class PerformanceController implements FirebasePerformance { constructor(readonly app: FirebaseApp) { if (Api.getInstance().requiredApisAvailable()) { - setupTransportService(); - getInitializationPromise().then(setupOobResources, setupOobResources); - } else { - consoleLogger.info( - 'Firebase Performance cannot start if browser does not support fetch and Promise or cookie is disabled.' - ); + validateIndexedDBOpenable() + .then(isAvailable => { + if (isAvailable) { + setupTransportService(); + getInitializationPromise().then( + setupOobResources, + setupOobResources + ); + } + }) + .catch(error => { + consoleLogger.info(`Environment doesn't support IndexedDB: ${error}`); + }); } } diff --git a/packages/performance/src/services/api_service.test.ts b/packages/performance/src/services/api_service.test.ts index 1f71b03359e..32ac012ffc3 100644 --- a/packages/performance/src/services/api_service.test.ts +++ b/packages/performance/src/services/api_service.test.ts @@ -19,7 +19,6 @@ import { stub } from 'sinon'; import { expect } from 'chai'; import { Api, setupApi } from './api_service'; import '../../test/setup'; - describe('Firebase Performance > api_service', () => { const PAGE_URL = 'http://www.test.com/abcd?a=2'; const PERFORMANCE_ENTRY: PerformanceEntry = { @@ -47,6 +46,7 @@ describe('Firebase Performance > api_service', () => { ]); // This is to make sure the test page is not changed by changing the href of location object. mockWindow.location = { ...self.location, href: PAGE_URL }; + setupApi(mockWindow); api = Api.getInstance(); }); diff --git a/packages/performance/src/services/api_service.ts b/packages/performance/src/services/api_service.ts index ce0bd9a67b1..bbe47f9ad85 100644 --- a/packages/performance/src/services/api_service.ts +++ b/packages/performance/src/services/api_service.ts @@ -16,7 +16,8 @@ */ import { ERROR_FACTORY, ErrorCode } from '../utils/errors'; - +import { isIndexedDBAvailable } from '@firebase/util'; +import { consoleLogger } from '../utils/console_logger'; declare global { interface Window { PerformanceObserver: typeof PerformanceObserver; @@ -110,10 +111,23 @@ export class Api { } requiredApisAvailable(): boolean { - if (fetch && Promise && this.navigator && this.navigator.cookieEnabled) { - return true; + if ( + !fetch || + !Promise || + !this.navigator || + !this.navigator.cookieEnabled + ) { + consoleLogger.info( + 'Firebase Performance cannot start if browser does not support fetch and Promise or cookie is disabled.' + ); + return false; + } + + if (!isIndexedDBAvailable()) { + consoleLogger.info('IndexedDB is not supported by current browswer'); + return false; } - return false; + return true; } setupObserver( diff --git a/packages/performance/src/services/perf_logger.ts b/packages/performance/src/services/perf_logger.ts index fb786978ce6..2d2daa22fca 100644 --- a/packages/performance/src/services/perf_logger.ts +++ b/packages/performance/src/services/perf_logger.ts @@ -114,6 +114,7 @@ export function logTrace(trace: Trace): void { if (!Api.getInstance().requiredApisAvailable()) { return; } + // Only log the page load auto traces if page is visible. if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) { return;