Skip to content

Commit f16f6d0

Browse files
authored
Merge ed6fa88 into 5ae7365
2 parents 5ae7365 + ed6fa88 commit f16f6d0

File tree

7 files changed

+84
-38
lines changed

7 files changed

+84
-38
lines changed

packages-exp/messaging-exp/src/api.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,21 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { FirebaseApp, _getProvider, getApp } from '@firebase/app-exp';
19+
import { FirebaseMessaging, MessagePayload } from './interfaces/public-types';
1820
import {
19-
FirebaseMessaging,
20-
MessagePayload,
2121
NextFn,
2222
Observer,
23-
Unsubscribe
24-
} from './interfaces/public-types';
23+
Unsubscribe,
24+
getModularInstance
25+
} from '@firebase/util';
2526

2627
import { MessagingService } from './messaging-service';
2728
import { Provider } from '@firebase/component';
2829
import { deleteToken as _deleteToken } from './api/deleteToken';
29-
import { _getProvider, FirebaseApp, getApp } from '@firebase/app-exp';
3030
import { getToken as _getToken } from './api/getToken';
3131
import { onBackgroundMessage as _onBackgroundMessage } from './api/onBackgroundMessage';
3232
import { onMessage as _onMessage } from './api/onMessage';
33-
import { getModularInstance } from '@firebase/util';
3433

3534
/**
3635
* Retrieves a firebase messaging instance.
@@ -131,7 +130,7 @@ export function onMessage(
131130
*
132131
* @returns To stop listening for messages execute this returned function
133132
*
134-
* make it internal to hide it from the browser entrypoint
133+
* make it internal to hide it from the browser entry point.
135134
* @internal
136135
*/
137136
export function onBackgroundMessage(

packages-exp/messaging-exp/src/helpers/isSupported.ts renamed to packages-exp/messaging-exp/src/api/isSupported.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @license
3-
* Copyright 2019 Google LLC
3+
* Copyright 2020 Google LLC
44
*
55
* Licensed under the Apache License, Version 2.0 (the "License");
66
* you may not use this file except in compliance with the License.
@@ -15,21 +15,14 @@
1515
* limitations under the License.
1616
*/
1717

18-
export function isSupported(): boolean {
19-
if (self && 'ServiceWorkerGlobalScope' in self) {
20-
// Running in ServiceWorker context
21-
return isSWControllerSupported();
22-
} else {
23-
// Assume we are in the window context.
24-
return isWindowControllerSupported();
25-
}
26-
}
18+
import { validateIndexedDBOpenable } from '@firebase/util';
2719

28-
/**
29-
* Checks to see if the required APIs exist.
30-
*/
31-
function isWindowControllerSupported(): boolean {
20+
export async function isWindowSupported(): Promise<boolean> {
21+
// firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing
22+
// might be prohibited to run. In these contexts, an error would be thrown during the messaging
23+
// instantiating phase, informing the developers to import/call isSupported for special handling.
3224
return (
25+
(await validateIndexedDBOpenable()) &&
3326
'indexedDB' in window &&
3427
indexedDB !== null &&
3528
navigator.cookieEnabled &&
@@ -45,8 +38,12 @@ function isWindowControllerSupported(): boolean {
4538
/**
4639
* Checks to see if the required APIs exist within SW Context.
4740
*/
48-
function isSWControllerSupported(): boolean {
41+
export async function isSwSupported(): Promise<boolean> {
42+
// firebase-js-sdk/issues/2393 reveals that idb#open in Safari iframe and Firefox private browsing
43+
// might be prohibited to run. In these contexts, an error would be thrown during the messaging
44+
// instantiating phase, informing the developers to import/call isSupported for special handling.
4945
return (
46+
(await validateIndexedDBOpenable()) &&
5047
'indexedDB' in self &&
5148
indexedDB !== null &&
5249
'PushManager' in self &&

packages-exp/messaging-exp/src/helpers/register.ts

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,27 @@ import {
2222
InstanceFactory
2323
} from '@firebase/component';
2424
import { ERROR_FACTORY, ErrorCode } from '../util/errors';
25+
import { isSwSupported, isWindowSupported } from '../api/isSupported';
2526

2627
import { MessagingService } from '../messaging-service';
2728
import { _registerComponent } from '@firebase/app-exp';
28-
import { isSupported } from './isSupported';
2929

30-
const messagingFactory: InstanceFactory<'messaging-exp'> = (
30+
const WindowMessagingFactory: InstanceFactory<'messaging-exp'> = (
3131
container: ComponentContainer
3232
) => {
33-
if (!isSupported()) {
34-
throw ERROR_FACTORY.create(ErrorCode.UNSUPPORTED_BROWSER);
35-
}
33+
// Conscious decision to make this async check non-blocking during the messaging instance
34+
// initialization phase for performance consideration. An error would be thrown latter for
35+
// developer's information. Developers can then choose to import and call `isSupported` for
36+
// special handling.
37+
isWindowSupported()
38+
.then(isSupported => {
39+
if (!isSupported) {
40+
throw ERROR_FACTORY.create(ErrorCode.UNSUPPORTED_BROWSER);
41+
}
42+
})
43+
.catch(_ => {
44+
throw ERROR_FACTORY.create(ErrorCode.INDEXED_DB_UNSUPPORTED);
45+
});
3646

3747
return new MessagingService(
3848
container.getProvider('app-exp').getImmediate(),
@@ -41,8 +51,38 @@ const messagingFactory: InstanceFactory<'messaging-exp'> = (
4151
);
4252
};
4353

44-
export function registerMessaging(): void {
54+
const SwMessagingFactory: InstanceFactory<'messaging-exp'> = (
55+
container: ComponentContainer
56+
) => {
57+
// Conscious decision to make this async check non-blocking during the messaging instance
58+
// initialization phase for performance consideration. An error would be thrown latter for
59+
// developer's information. Developers can then choose to import and call `isSupported` for
60+
// special handling.
61+
isSwSupported()
62+
.then(isSupported => {
63+
if (!isSupported) {
64+
throw ERROR_FACTORY.create(ErrorCode.UNSUPPORTED_BROWSER);
65+
}
66+
})
67+
.catch(_ => {
68+
throw ERROR_FACTORY.create(ErrorCode.INDEXED_DB_UNSUPPORTED);
69+
});
70+
71+
return new MessagingService(
72+
container.getProvider('app-exp').getImmediate(),
73+
container.getProvider('installations-exp-internal').getImmediate(),
74+
container.getProvider('analytics-internal')
75+
);
76+
};
77+
78+
export function registerMessagingInWindow(): void {
79+
_registerComponent(
80+
new Component('messaging-exp', WindowMessagingFactory, ComponentType.PUBLIC)
81+
);
82+
}
83+
84+
export function registerMessagingInSw(): void {
4585
_registerComponent(
46-
new Component('messaging-exp', messagingFactory, ComponentType.PUBLIC)
86+
new Component('messaging-exp', SwMessagingFactory, ComponentType.PUBLIC)
4787
);
4888
}

packages-exp/messaging-exp/src/index.sw.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { FirebaseMessaging } from './interfaces/public-types';
19-
import { registerMessaging } from './helpers/register';
2018
import '@firebase/installations-exp';
2119

20+
import { FirebaseMessaging } from './interfaces/public-types';
21+
import { registerMessagingInSw } from './helpers/register';
22+
2223
export { onBackgroundMessage, getMessaging } from './api';
24+
export { isSwSupported as isSupported } from './api/isSupported';
2325

2426
declare module '@firebase/component' {
2527
interface NameServiceMapping {
2628
'messaging-exp': FirebaseMessaging;
2729
}
2830
}
2931

30-
registerMessaging();
32+
registerMessagingInSw();

packages-exp/messaging-exp/src/index.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,19 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { FirebaseMessaging } from './interfaces/public-types';
19-
import { registerMessaging } from './helpers/register';
2018
import '@firebase/installations-exp';
2119

20+
import { FirebaseMessaging } from './interfaces/public-types';
21+
import { registerMessagingInWindow } from './helpers/register';
22+
2223
export {
2324
getToken,
2425
deleteToken,
2526
onMessage,
2627
getMessaging,
2728
onBackgroundMessage
2829
} from './api';
30+
export { isWindowSupported as isSupported } from './api/isSupported';
2931
export * from './interfaces/public-types';
3032

3133
declare module '@firebase/component' {
@@ -34,4 +36,4 @@ declare module '@firebase/component' {
3436
}
3537
}
3638

37-
registerMessaging();
39+
registerMessagingInWindow();

packages-exp/messaging-exp/src/util/errors.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export const enum ErrorCode {
2424
PERMISSION_DEFAULT = 'permission-default',
2525
PERMISSION_BLOCKED = 'permission-blocked',
2626
UNSUPPORTED_BROWSER = 'unsupported-browser',
27+
INDEXED_DB_UNSUPPORTED = 'indexed-db-unsupported',
2728
FAILED_DEFAULT_REGISTRATION = 'failed-service-worker-registration',
2829
TOKEN_SUBSCRIBE_FAILED = 'token-subscribe-failed',
2930
TOKEN_SUBSCRIBE_NO_TOKEN = 'token-subscribe-no-token',
@@ -50,6 +51,8 @@ export const ERROR_MAP: ErrorMap<ErrorCode> = {
5051
'The notification permission was not granted and blocked instead.',
5152
[ErrorCode.UNSUPPORTED_BROWSER]:
5253
"This browser doesn't support the API's required to use the firebase SDK.",
54+
[ErrorCode.INDEXED_DB_UNSUPPORTED]:
55+
"This browser doesn't support indexedDb.open() (ex. Safari iFrame, Firefox Private Browsing, etc)",
5356
[ErrorCode.FAILED_DEFAULT_REGISTRATION]:
5457
'We are unable to register the default service worker. {$browserErrorMessage}',
5558
[ErrorCode.TOKEN_SUBSCRIBE_FAILED]:

packages/util/src/environment.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,21 +144,24 @@ export function isIndexedDBAvailable(): boolean {
144144
}
145145

146146
/**
147-
* This method validates browser context for indexedDB by opening a dummy indexedDB database and reject
147+
* This method validates browser/sw context for indexedDB by opening a dummy indexedDB database and reject
148148
* if errors occur during the database open operation.
149+
*
150+
* @throws exception if current browser/sw context can't run idb.open (ex: Safari iframe, Firefox
151+
* private browsing)
149152
*/
150153
export function validateIndexedDBOpenable(): Promise<boolean> {
151154
return new Promise((resolve, reject) => {
152155
try {
153156
let preExist: boolean = true;
154157
const DB_CHECK_NAME =
155158
'validate-browser-context-for-indexeddb-analytics-module';
156-
const request = window.indexedDB.open(DB_CHECK_NAME);
159+
const request = self.indexedDB.open(DB_CHECK_NAME);
157160
request.onsuccess = () => {
158161
request.result.close();
159162
// delete database only when it doesn't pre-exist
160163
if (!preExist) {
161-
window.indexedDB.deleteDatabase(DB_CHECK_NAME);
164+
self.indexedDB.deleteDatabase(DB_CHECK_NAME);
162165
}
163166
resolve(true);
164167
};

0 commit comments

Comments
 (0)