Skip to content

Issue 2393 #3160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/firebase/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,7 @@ declare namespace firebase.performance {
*/
getAttributes(): { [key: string]: string };
}
function isSupported(): boolean;
}

/**
Expand Down Expand Up @@ -1771,6 +1772,8 @@ declare namespace firebase.remoteConfig {
* Defines levels of Remote Config logging.
*/
export type LogLevel = 'debug' | 'error' | 'silent';

function isSupported(): boolean;
}

declare namespace firebase.functions {
Expand Down
51 changes: 50 additions & 1 deletion packages/performance/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export function registerPerformance(instance: FirebaseNamespace): void {
return new PerformanceController(app);
};

const NAMESPACE_EXPORTS = {
isSupported
};

// Register performance with firebase-app.
(instance as _FirebaseNamespace).INTERNAL.registerComponent(
new Component(
Expand All @@ -60,11 +64,14 @@ export function registerPerformance(instance: FirebaseNamespace): void {
const installations = container
.getProvider('installations')
.getImmediate();
if (!isSupported()) {
throw ERROR_FACTORY.create(ErrorCode.UNSUPPORTED_BROWSER);
}

return factoryMethod(app, installations);
},
ComponentType.PUBLIC
)
).setServiceProps(NAMESPACE_EXPORTS)
);

instance.registerVersion(name, version);
Expand All @@ -76,9 +83,51 @@ declare module '@firebase/app-types' {
interface FirebaseNamespace {
performance?: {
(app?: FirebaseApp): FirebasePerformance;
isSupprted(): boolean;
};
}
interface FirebaseApp {
performance?(): FirebasePerformance;
}
}

function isSupported(): boolean {
if (self && 'ServiceWorkerGlobalScope' in self) {
// Running in ServiceWorker context
return isSWControllerSupported();
} else {
// Assume we are in the window context.
return isWindowControllerSupported();
}
}

/**
* Checks to see if the required APIs exist.
*/
function isWindowControllerSupported(): boolean {
return (
'indexedDB' in window &&
indexedDB !== null &&
navigator.cookieEnabled &&
'serviceWorker' in navigator &&
'PushManager' in window &&
'Notification' in window &&
'fetch' in window &&
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
PushSubscription.prototype.hasOwnProperty('getKey')
);
}

/**
* Checks to see if the required APIs exist within SW Context.
*/
function isSWControllerSupported(): boolean {
return (
'indexedDB' in self &&
indexedDB !== null &&
'PushManager' in self &&
'Notification' in self &&
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
PushSubscription.prototype.hasOwnProperty('getKey')
);
}
7 changes: 5 additions & 2 deletions packages/performance/src/utils/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export const enum ErrorCode {
INVALID_ATTRIBUTE_NAME = 'invalid attribute name',
INVALID_ATTRIBUTE_VALUE = 'invalid attribute value',
INVALID_CUSTOM_METRIC_NAME = 'invalid custom metric name',
INVALID_STRING_MERGER_PARAMETER = 'invalid String merger input'
INVALID_STRING_MERGER_PARAMETER = 'invalid String merger input',
UNSUPPORTED_BROWSER = 'unsupported-browser'
}

const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
Expand All @@ -52,7 +53,9 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
[ErrorCode.INVALID_CUSTOM_METRIC_NAME]:
'Custom metric name {$customMetricName} is invalid',
[ErrorCode.INVALID_STRING_MERGER_PARAMETER]:
'Input for String merger is invalid, contact support team to resolve.'
'Input for String merger is invalid, contact support team to resolve.',
[ErrorCode.UNSUPPORTED_BROWSER]:
"This browser doesn't support the API's required to use the firebase SDK."
};

interface ErrorParams {
Expand Down
58 changes: 53 additions & 5 deletions packages/remote-config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,17 @@ declare global {
}
}

const NAMESPACE_EXPORTS = {
isSupported
};

export function registerRemoteConfig(
firebaseInstance: _FirebaseNamespace
): void {
firebaseInstance.INTERNAL.registerComponent(
new Component(
'remoteConfig',
remoteConfigFactory,
ComponentType.PUBLIC
).setMultipleInstances(true)
new Component('remoteConfig', remoteConfigFactory, ComponentType.PUBLIC)
.setMultipleInstances(true)
.setServiceProps(NAMESPACE_EXPORTS)
);

firebaseInstance.registerVersion(packageName, version);
Expand All @@ -72,6 +74,10 @@ export function registerRemoteConfig(
throw ERROR_FACTORY.create(ErrorCode.REGISTRATION_WINDOW);
}

if (!isSupported()) {
throw ERROR_FACTORY.create(ErrorCode.UNSUPPORTED_BROWSER);
}

// Normalizes optional inputs.
const { projectId, apiKey, appId } = app.options;
if (!projectId) {
Expand Down Expand Up @@ -133,9 +139,51 @@ declare module '@firebase/app-types' {
interface FirebaseNamespace {
remoteConfig?: {
(app?: FirebaseApp): RemoteConfigType;
isSupported(): boolean;
};
}
interface FirebaseApp {
remoteConfig(): RemoteConfigType;
}
}

function isSupported(): boolean {
if (self && 'ServiceWorkerGlobalScope' in self) {
// Running in ServiceWorker context
return isSWControllerSupported();
} else {
// Assume we are in the window context.
return isWindowControllerSupported();
}
}

/**
* Checks to see if the required APIs exist.
*/
function isWindowControllerSupported(): boolean {
return (
'indexedDB' in window &&
indexedDB !== null &&
navigator.cookieEnabled &&
'serviceWorker' in navigator &&
'PushManager' in window &&
'Notification' in window &&
'fetch' in window &&
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
PushSubscription.prototype.hasOwnProperty('getKey')
);
}

/**
* Checks to see if the required APIs exist within SW Context.
*/
function isSWControllerSupported(): boolean {
return (
'indexedDB' in self &&
indexedDB !== null &&
'PushManager' in self &&
'Notification' in self &&
ServiceWorkerRegistration.prototype.hasOwnProperty('showNotification') &&
PushSubscription.prototype.hasOwnProperty('getKey')
);
}
7 changes: 5 additions & 2 deletions packages/remote-config/src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export const enum ErrorCode {
FETCH_TIMEOUT = 'fetch-timeout',
FETCH_THROTTLE = 'fetch-throttle',
FETCH_PARSE = 'fetch-client-parse',
FETCH_STATUS = 'fetch-status'
FETCH_STATUS = 'fetch-status',
UNSUPPORTED_BROWSER = 'unsupported-browser'
}

const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
Expand Down Expand Up @@ -64,7 +65,9 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
'Fetch client could not parse response.' +
' Original error: {$originalErrorMessage}.',
[ErrorCode.FETCH_STATUS]:
'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.'
'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.',
[ErrorCode.UNSUPPORTED_BROWSER]:
"This browser doesn't support the API's required to use the firebase SDK."
};

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