diff --git a/.changeset/long-shirts-explode.md b/.changeset/long-shirts-explode.md new file mode 100644 index 00000000000..84685d7283d --- /dev/null +++ b/.changeset/long-shirts-explode.md @@ -0,0 +1,5 @@ +--- +"@firebase/storage": patch +--- + +Fixed issue where if btoa wasn't supported in the environment, then the user would get a generic message. diff --git a/packages/storage/src/implementation/error.ts b/packages/storage/src/implementation/error.ts index fa12d76d763..da90e3900ee 100644 --- a/packages/storage/src/implementation/error.ts +++ b/packages/storage/src/implementation/error.ts @@ -261,6 +261,13 @@ export function noDownloadURL(): StorageError { ); } +export function missingPolyFill(polyFill: string): StorageError { + return new StorageError( + StorageErrorCode.UNSUPPORTED_ENVIRONMENT, + `${polyFill} is missing. Make sure to install the required polyfills. See https://firebase.google.com/docs/web/environments-js-sdk#polyfills for more information.` + ); +} + /** * @internal */ diff --git a/packages/storage/src/implementation/string.ts b/packages/storage/src/implementation/string.ts index 0462576128c..6fbac66f55a 100644 --- a/packages/storage/src/implementation/string.ts +++ b/packages/storage/src/implementation/string.ts @@ -184,6 +184,9 @@ export function base64Bytes_(format: StringFormat, value: string): Uint8Array { try { bytes = decodeBase64(value); } catch (e) { + if ((e as Error).message.includes('polyfill')) { + throw e; + } throw invalidFormat(format, 'Invalid character found'); } const array = new Uint8Array(bytes.length); diff --git a/packages/storage/src/platform/browser/base64.ts b/packages/storage/src/platform/browser/base64.ts index 7c8d3d5586e..f1cc1c4af15 100644 --- a/packages/storage/src/platform/browser/base64.ts +++ b/packages/storage/src/platform/browser/base64.ts @@ -15,8 +15,13 @@ * limitations under the License. */ +import { missingPolyFill } from '../../implementation/error'; + /** Converts a Base64 encoded string to a binary string. */ export function decodeBase64(encoded: string): string { + if (typeof atob === 'undefined') { + throw missingPolyFill('base-64'); + } return atob(encoded); } diff --git a/packages/storage/test/browser/string.browser.test.ts b/packages/storage/test/browser/string.browser.test.ts new file mode 100644 index 00000000000..4618ecb70f8 --- /dev/null +++ b/packages/storage/test/browser/string.browser.test.ts @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { expect } from 'chai'; +import { missingPolyFill } from '../../src/implementation/error'; +import { dataFromString, StringFormat } from '../../src/implementation/string'; +import { assertThrows } from '../unit/testshared'; + +describe('String browser tests', () => { + it('should reject if atob is undefined', () => { + const originalAToB = global.atob; + // @ts-ignore + global.atob = undefined; + const str = 'CpYlM1-XsGxTd1n6izHMU_yY3Bw='; + + const error = assertThrows(() => { + dataFromString(StringFormat.BASE64URL, str); + }, 'storage/unsupported-environment'); + expect(error.message).to.equal(missingPolyFill('base-64').message); + global.atob = originalAToB; + }); +});