Skip to content

Commit 92bf2c3

Browse files
committed
Separate checks
1 parent b5b5058 commit 92bf2c3

File tree

5 files changed

+117
-154
lines changed

5 files changed

+117
-154
lines changed

packages/analytics/index.test.ts

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
getFakeInstallations
3131
} from './testing/get-fake-firebase-services';
3232
import { FirebaseApp } from '@firebase/app-types';
33-
import { GtagCommand, EventName } from './src/constants';
33+
import { GtagCommand, EventName, GA_FID_KEY } from './src/constants';
3434
import { findGtagScriptOnPage } from './src/helpers';
3535
import { removeGtagScript } from './testing/gtag-script-util';
3636
import { Deferred } from '@firebase/util';
@@ -214,35 +214,20 @@ describe('FirebaseAnalytics instance tests', () => {
214214
clock.restore();
215215
warnStub.restore();
216216
idbOpenStub.restore();
217+
gtagStub.resetHistory();
217218
});
218-
it('Warns on logEvent if cookies not available', async () => {
219+
it('Warns on initialization if cookies not available', async () => {
219220
cookieStub = stub(navigator, 'cookieEnabled').value(false);
220221
analyticsInstance = analyticsFactory(app, installations);
221-
analyticsInstance.logEvent(EventName.ADD_PAYMENT_INFO, {
222-
currency: 'USD'
223-
});
224-
// Successfully resolves fake IDB open request.
225-
fakeRequest.onsuccess();
226-
// Clear promise chain started by logEvent.
227-
await clock.runAllAsync();
228-
expect(gtagStub).to.not.have.been.called;
229222
expect(warnStub.args[0][1]).to.include(
230223
AnalyticsError.INVALID_ANALYTICS_CONTEXT
231224
);
232225
expect(warnStub.args[0][1]).to.include('Cookies');
233226
cookieStub.restore();
234227
});
235-
it('Warns on logEvent if in browser extension', async () => {
228+
it('Warns on initialization if in browser extension', async () => {
236229
window.chrome = { runtime: { id: 'blah' } };
237230
analyticsInstance = analyticsFactory(app, installations);
238-
analyticsInstance.logEvent(EventName.ADD_PAYMENT_INFO, {
239-
currency: 'USD'
240-
});
241-
// Successfully resolves fake IDB open request.
242-
fakeRequest.onsuccess();
243-
// Clear promise chain started by logEvent.
244-
await clock.runAllAsync();
245-
expect(gtagStub).to.not.have.been.called;
246231
expect(warnStub.args[0][1]).to.include(
247232
AnalyticsError.INVALID_ANALYTICS_CONTEXT
248233
);
@@ -257,7 +242,11 @@ describe('FirebaseAnalytics instance tests', () => {
257242
});
258243
// Clear promise chain started by logEvent.
259244
await clock.runAllAsync();
260-
expect(gtagStub).to.not.have.been.called;
245+
// gtag config call omits FID
246+
expect(gtagStub).to.be.calledWith('config', 'abcd-efgh', {
247+
update: true,
248+
origin: 'firebase'
249+
});
261250
expect(warnStub.args[0][1]).to.include(
262251
AnalyticsError.INVALID_ANALYTICS_CONTEXT
263252
);
@@ -273,7 +262,11 @@ describe('FirebaseAnalytics instance tests', () => {
273262
});
274263
// Clear promise chain started by logEvent.
275264
await clock.runAllAsync();
276-
expect(gtagStub).to.not.have.been.called;
265+
// gtag config call omits FID
266+
expect(gtagStub).to.be.calledWith('config', 'abcd-efgh', {
267+
update: true,
268+
origin: 'firebase'
269+
});
277270
expect(warnStub.args[0][1]).to.include(
278271
AnalyticsError.INVALID_ANALYTICS_CONTEXT
279272
);

packages/analytics/src/factory.ts

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,7 @@ import {
3838
import { AnalyticsError, ERROR_FACTORY } from './errors';
3939
import { FirebaseApp } from '@firebase/app-types';
4040
import { FirebaseInstallations } from '@firebase/installations-types';
41-
import {
42-
isIndexedDBAvailable,
43-
areCookiesEnabled,
44-
isBrowserExtension,
45-
validateIndexedDBOpenable
46-
} from '@firebase/util';
41+
import { areCookiesEnabled, isBrowserExtension } from '@firebase/util';
4742
import { initializeIds } from './initialize-ids';
4843
import { logger } from './logger';
4944
import { FirebaseService } from '@firebase/app-types/private';
@@ -158,40 +153,30 @@ export function settings(options: SettingsOptions): void {
158153
* If environment mismatches are found, throws an INVALID_ANALYTICS_CONTEXT
159154
* error that also lists details for each mismatch found.
160155
*/
161-
async function validateBrowserContext(): Promise<boolean> {
156+
function warnOnBrowserContextMismatch(): void {
162157
const mismatchedEnvMessages = [];
163158
if (isBrowserExtension()) {
164159
mismatchedEnvMessages.push('This is a browser extension environment.');
165160
}
166161
if (!areCookiesEnabled()) {
167162
mismatchedEnvMessages.push('Cookies are not available.');
168163
}
169-
if (!isIndexedDBAvailable()) {
170-
mismatchedEnvMessages.push(
171-
'IndexedDB is not available in this environment.'
172-
);
173-
} else {
174-
try {
175-
await validateIndexedDBOpenable();
176-
} catch (e) {
177-
mismatchedEnvMessages.push(e);
178-
}
179-
}
180164
if (mismatchedEnvMessages.length > 0) {
181165
const details = mismatchedEnvMessages
182166
.map((message, index) => `(${index + 1}) ${message}`)
183167
.join(' ');
184-
throw ERROR_FACTORY.create(AnalyticsError.INVALID_ANALYTICS_CONTEXT, {
168+
const err = ERROR_FACTORY.create(AnalyticsError.INVALID_ANALYTICS_CONTEXT, {
185169
errorInfo: details
186170
});
171+
logger.warn(err.message);
187172
}
188-
return true;
189173
}
190174

191175
export function factory(
192176
app: FirebaseApp,
193177
installations: FirebaseInstallations
194178
): FirebaseAnalytics {
179+
warnOnBrowserContextMismatch();
195180
const appId = app.options.appId;
196181
if (!appId) {
197182
throw ERROR_FACTORY.create(AnalyticsError.NO_APP_ID);
@@ -237,14 +222,12 @@ export function factory(
237222
}
238223
// Async but non-blocking.
239224
// This map reflects the completion state of all promises for each appId.
240-
initializationPromisesMap[appId] = validateBrowserContext().then(() =>
241-
initializeIds(
242-
app,
243-
dynamicConfigPromisesList,
244-
measurementIdToAppId,
245-
installations,
246-
gtagCoreFunction
247-
)
225+
initializationPromisesMap[appId] = initializeIds(
226+
app,
227+
dynamicConfigPromisesList,
228+
measurementIdToAppId,
229+
installations,
230+
gtagCoreFunction
248231
);
249232

250233
const analyticsInstance: FirebaseAnalyticsInternal = {

packages/analytics/src/functions.ts

Lines changed: 43 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ import {
2323
EventParams
2424
} from '@firebase/analytics-types';
2525
import { GtagCommand } from './constants';
26-
import { AnalyticsError } from './errors';
27-
import { logger } from './logger';
28-
2926
/**
3027
* Logs an analytics event through the Firebase SDK.
3128
*
@@ -40,24 +37,16 @@ export async function logEvent(
4037
eventParams?: EventParams,
4138
options?: AnalyticsCallOptions
4239
): Promise<void> {
43-
try {
44-
if (options && options.global) {
45-
gtagFunction(GtagCommand.EVENT, eventName, eventParams);
46-
return;
47-
} else {
48-
const measurementId = await initializationPromise;
49-
const params: EventParams | ControlParams = {
50-
...eventParams,
51-
'send_to': measurementId
52-
};
53-
gtagFunction(GtagCommand.EVENT, eventName, params);
54-
}
55-
} catch (e) {
56-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
57-
logger.warn(e.message);
58-
} else {
59-
throw e;
60-
}
40+
if (options && options.global) {
41+
gtagFunction(GtagCommand.EVENT, eventName, eventParams);
42+
return;
43+
} else {
44+
const measurementId = await initializationPromise;
45+
const params: EventParams | ControlParams = {
46+
...eventParams,
47+
'send_to': measurementId
48+
};
49+
gtagFunction(GtagCommand.EVENT, eventName, params);
6150
}
6251
}
6352

@@ -73,23 +62,15 @@ export async function setCurrentScreen(
7362
screenName: string | null,
7463
options?: AnalyticsCallOptions
7564
): Promise<void> {
76-
try {
77-
if (options && options.global) {
78-
gtagFunction(GtagCommand.SET, { 'screen_name': screenName });
79-
return Promise.resolve();
80-
} else {
81-
const measurementId = await initializationPromise;
82-
gtagFunction(GtagCommand.CONFIG, measurementId, {
83-
update: true,
84-
'screen_name': screenName
85-
});
86-
}
87-
} catch (e) {
88-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
89-
logger.warn(e.message);
90-
} else {
91-
throw e;
92-
}
65+
if (options && options.global) {
66+
gtagFunction(GtagCommand.SET, { 'screen_name': screenName });
67+
return Promise.resolve();
68+
} else {
69+
const measurementId = await initializationPromise;
70+
gtagFunction(GtagCommand.CONFIG, measurementId, {
71+
update: true,
72+
'screen_name': screenName
73+
});
9374
}
9475
}
9576

@@ -105,23 +86,15 @@ export async function setUserId(
10586
id: string | null,
10687
options?: AnalyticsCallOptions
10788
): Promise<void> {
108-
try {
109-
if (options && options.global) {
110-
gtagFunction(GtagCommand.SET, { 'user_id': id });
111-
return Promise.resolve();
112-
} else {
113-
const measurementId = await initializationPromise;
114-
gtagFunction(GtagCommand.CONFIG, measurementId, {
115-
update: true,
116-
'user_id': id
117-
});
118-
}
119-
} catch (e) {
120-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
121-
logger.warn(e.message);
122-
} else {
123-
throw e;
124-
}
89+
if (options && options.global) {
90+
gtagFunction(GtagCommand.SET, { 'user_id': id });
91+
return Promise.resolve();
92+
} else {
93+
const measurementId = await initializationPromise;
94+
gtagFunction(GtagCommand.CONFIG, measurementId, {
95+
update: true,
96+
'user_id': id
97+
});
12598
}
12699
}
127100

@@ -137,28 +110,20 @@ export async function setUserProperties(
137110
properties: CustomParams,
138111
options?: AnalyticsCallOptions
139112
): Promise<void> {
140-
try {
141-
if (options && options.global) {
142-
const flatProperties: { [key: string]: unknown } = {};
143-
for (const key of Object.keys(properties)) {
144-
// use dot notation for merge behavior in gtag.js
145-
flatProperties[`user_properties.${key}`] = properties[key];
146-
}
147-
gtagFunction(GtagCommand.SET, flatProperties);
148-
return Promise.resolve();
149-
} else {
150-
const measurementId = await initializationPromise;
151-
gtagFunction(GtagCommand.CONFIG, measurementId, {
152-
update: true,
153-
'user_properties': properties
154-
});
155-
}
156-
} catch (e) {
157-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
158-
logger.warn(e.message);
159-
} else {
160-
throw e;
113+
if (options && options.global) {
114+
const flatProperties: { [key: string]: unknown } = {};
115+
for (const key of Object.keys(properties)) {
116+
// use dot notation for merge behavior in gtag.js
117+
flatProperties[`user_properties.${key}`] = properties[key];
161118
}
119+
gtagFunction(GtagCommand.SET, flatProperties);
120+
return Promise.resolve();
121+
} else {
122+
const measurementId = await initializationPromise;
123+
gtagFunction(GtagCommand.CONFIG, measurementId, {
124+
update: true,
125+
'user_properties': properties
126+
});
162127
}
163128
}
164129

@@ -171,14 +136,6 @@ export async function setAnalyticsCollectionEnabled(
171136
initializationPromise: Promise<string>,
172137
enabled: boolean
173138
): Promise<void> {
174-
try {
175-
const measurementId = await initializationPromise;
176-
window[`ga-disable-${measurementId}`] = !enabled;
177-
} catch (e) {
178-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
179-
logger.warn(e.message);
180-
} else {
181-
throw e;
182-
}
183-
}
139+
const measurementId = await initializationPromise;
140+
window[`ga-disable-${measurementId}`] = !enabled;
184141
}

packages/analytics/src/helpers.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
MinimalDynamicConfig
2626
} from '@firebase/analytics-types';
2727
import { GtagCommand, GTAG_URL } from './constants';
28-
import { AnalyticsError } from './errors';
2928
import { logger } from './logger';
3029

3130
/**
@@ -96,12 +95,6 @@ async function gtagOnConfig(
9695
}
9796
}
9897
} catch (e) {
99-
// Thrown by an initializeIds promise in initializationPromisesMap before
100-
// making any fetches if indexedDB.open() is unavailable in the environment.
101-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
102-
logger.warn(e.message);
103-
return;
104-
}
10598
logger.error(e);
10699
}
107100
gtagCore(GtagCommand.CONFIG, measurementId, gtagParams);
@@ -173,12 +166,6 @@ async function gtagOnEvent(
173166
// Workaround for http://b/141370449 - third argument cannot be undefined.
174167
gtagCore(GtagCommand.EVENT, measurementId, gtagParams || {});
175168
} catch (e) {
176-
// Thrown by an initializeIds promise in initializationPromisesMap before
177-
// making any fetches if indexedDB.open() is unavailable in the environment.
178-
if (e.message.includes(AnalyticsError.INVALID_ANALYTICS_CONTEXT)) {
179-
logger.warn(e.message);
180-
return;
181-
}
182169
logger.error(e);
183170
}
184171
}

0 commit comments

Comments
 (0)