Skip to content

Commit 696cd52

Browse files
authored
Merge f053094 into 8d3aca7
2 parents 8d3aca7 + f053094 commit 696cd52

File tree

5 files changed

+80
-29
lines changed

5 files changed

+80
-29
lines changed

.changeset/blue-rice-ring.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"firebase": minor
3+
"@firebase/remote-config": minor
4+
---
5+
6+
Issue 2393 - Add environment check to Remote-Config Module

packages/firebase/index.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,15 @@ declare namespace firebase.remoteConfig {
17721772
* Defines levels of Remote Config logging.
17731773
*/
17741774
export type LogLevel = 'debug' | 'error' | 'silent';
1775+
/**
1776+
* Returns true if current browser context supports initialization of remote config module
1777+
* (`firebase.remoteConfig()`).
1778+
*
1779+
* Returns false otherwise.
1780+
*
1781+
*
1782+
*/
1783+
function isSupported(): Promise<boolean>;
17751784
}
17761785

17771786
declare namespace firebase.functions {

packages/remote-config/index.ts

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import { ERROR_FACTORY, ErrorCode } from './src/errors';
2828
import { RetryingClient } from './src/client/retrying_client';
2929
import { Logger, LogLevel as FirebaseLogLevel } from '@firebase/logger';
3030
import { name as packageName, version } from './package.json';
31+
import {
32+
isIndexedDBAvailable,
33+
validateIndexedDBOpenable
34+
} from '@firebase/util';
3135
import {
3236
Component,
3337
ComponentType,
@@ -48,11 +52,11 @@ export function registerRemoteConfig(
4852
firebaseInstance: _FirebaseNamespace
4953
): void {
5054
firebaseInstance.INTERNAL.registerComponent(
51-
new Component(
52-
'remoteConfig',
53-
remoteConfigFactory,
54-
ComponentType.PUBLIC
55-
).setMultipleInstances(true)
55+
new Component('remoteConfig', remoteConfigFactory, ComponentType.PUBLIC)
56+
.setMultipleInstances(true)
57+
.setServiceProps({
58+
isSupported
59+
})
5660
);
5761

5862
firebaseInstance.registerVersion(packageName, version);
@@ -71,7 +75,10 @@ export function registerRemoteConfig(
7175
if (typeof window === 'undefined') {
7276
throw ERROR_FACTORY.create(ErrorCode.REGISTRATION_WINDOW);
7377
}
74-
78+
// Guards against the SDK being used when indexedDB is not available.
79+
if (!isIndexedDBAvailable()) {
80+
throw ERROR_FACTORY.create(ErrorCode.INDEXED_DB_UNAVAILABLE);
81+
}
7582
// Normalizes optional inputs.
7683
const { projectId, apiKey, appId } = app.options;
7784
if (!projectId) {
@@ -139,3 +146,21 @@ declare module '@firebase/app-types' {
139146
remoteConfig(): RemoteConfigType;
140147
}
141148
}
149+
/**
150+
* this is a public static method provided to users that wraps two different checks:
151+
*
152+
* 1. check if IndexedDB is supported by the browser environment.
153+
* 2. check if the current browser context is valid for using IndexedDB.
154+
*
155+
*/
156+
async function isSupported(): Promise<boolean> {
157+
if (!isIndexedDBAvailable()) {
158+
return false;
159+
}
160+
161+
try {
162+
return await validateIndexedDBOpenable();
163+
} catch (error) {
164+
return false;
165+
}
166+
}

packages/remote-config/src/errors.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ export const enum ErrorCode {
3030
FETCH_TIMEOUT = 'fetch-timeout',
3131
FETCH_THROTTLE = 'fetch-throttle',
3232
FETCH_PARSE = 'fetch-client-parse',
33-
FETCH_STATUS = 'fetch-status'
33+
FETCH_STATUS = 'fetch-status',
34+
INDEXED_DB_UNAVAILABLE = 'indexed-db-unavailable'
3435
}
3536

3637
const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
@@ -64,7 +65,9 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
6465
'Fetch client could not parse response.' +
6566
' Original error: {$originalErrorMessage}.',
6667
[ErrorCode.FETCH_STATUS]:
67-
'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.'
68+
'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.',
69+
[ErrorCode.INDEXED_DB_UNAVAILABLE]:
70+
'Indexed DB is not supported by current browser'
6871
};
6972

7073
// Note this is effectively a type system binding a code to params. This approach overlaps with the

packages/remote-config/src/storage/storage.ts

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -75,28 +75,36 @@ type ProjectNamespaceKeyFieldValue =
7575
// Visible for testing.
7676
export function openDatabase(): Promise<IDBDatabase> {
7777
return new Promise((resolve, reject) => {
78-
const request = indexedDB.open(DB_NAME, DB_VERSION);
79-
request.onerror = event => {
80-
reject(toFirebaseError(event, ErrorCode.STORAGE_OPEN));
81-
};
82-
request.onsuccess = event => {
83-
resolve((event.target as IDBOpenDBRequest).result);
84-
};
85-
request.onupgradeneeded = event => {
86-
const db = (event.target as IDBOpenDBRequest).result;
78+
try {
79+
const request = indexedDB.open(DB_NAME, DB_VERSION);
80+
request.onerror = event => {
81+
reject(toFirebaseError(event, ErrorCode.STORAGE_OPEN));
82+
};
83+
request.onsuccess = event => {
84+
resolve((event.target as IDBOpenDBRequest).result);
85+
};
86+
request.onupgradeneeded = event => {
87+
const db = (event.target as IDBOpenDBRequest).result;
8788

88-
// We don't use 'break' in this switch statement, the fall-through
89-
// behavior is what we want, because if there are multiple versions between
90-
// the old version and the current version, we want ALL the migrations
91-
// that correspond to those versions to run, not only the last one.
92-
// eslint-disable-next-line default-case
93-
switch (event.oldVersion) {
94-
case 0:
95-
db.createObjectStore(APP_NAMESPACE_STORE, {
96-
keyPath: 'compositeKey'
97-
});
98-
}
99-
};
89+
// We don't use 'break' in this switch statement, the fall-through
90+
// behavior is what we want, because if there are multiple versions between
91+
// the old version and the current version, we want ALL the migrations
92+
// that correspond to those versions to run, not only the last one.
93+
// eslint-disable-next-line default-case
94+
switch (event.oldVersion) {
95+
case 0:
96+
db.createObjectStore(APP_NAMESPACE_STORE, {
97+
keyPath: 'compositeKey'
98+
});
99+
}
100+
};
101+
} catch (error) {
102+
reject(
103+
ERROR_FACTORY.create(ErrorCode.STORAGE_OPEN, {
104+
originalErrorMessage: error
105+
})
106+
);
107+
}
100108
});
101109
}
102110

0 commit comments

Comments
 (0)