diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_web.dart b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_web.dart index ccb8884fcb45..d3f14a894066 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_web.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/firebase_storage_web.dart @@ -115,13 +115,13 @@ class FirebaseStorageWeb extends FirebaseStoragePlatform { @override void setMaxOperationRetryTime(int time) { _maxOperationRetryTime = time; - delegate.setMaxOperationRetryTime(time); + delegate.maxOperationRetryTime = time; } /// The new maximum upload retry time in milliseconds. @override void setMaxUploadRetryTime(int time) { - delegate.setMaxUploadRetryTime(time); + delegate.maxUploadRetryTime = time; } /// The new maximum download retry time in milliseconds. diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/interop/firebase_interop.dart b/packages/firebase_storage/firebase_storage_web/lib/src/interop/firebase_interop.dart deleted file mode 100644 index 1ef6ce6bf9a8..000000000000 --- a/packages/firebase_storage/firebase_storage_web/lib/src/interop/firebase_interop.dart +++ /dev/null @@ -1,22 +0,0 @@ -// ignore_for_file: require_trailing_commas -// Copyright 2020, the Chromium project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// ignore_for_file: public_member_api_docs - -@JS('firebase') -library firebase_interop.firebase; - -import 'package:firebase_core_web/firebase_core_web_interop.dart'; - -import 'package:js/js.dart'; -import 'storage_interop.dart'; - -@JS() -abstract class AppStorageJsImpl extends AppJsImpl { - external StorageJsImpl storage([String? bucket]); -} - -@JS() -external AppStorageJsImpl app([String? name]); diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart index 02b0aeeaf499..cfbe8cf2e341 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage.dart @@ -8,9 +8,10 @@ import 'dart:async'; import 'package:firebase_core_web/firebase_core_web_interop.dart'; +import 'package:firebase_core_web/firebase_core_web_interop.dart' + as core_interop; import 'package:js/js.dart'; -import 'firebase_interop.dart' as firebase_interop; import 'storage_interop.dart' as storage_interop; export 'storage_interop.dart'; @@ -23,11 +24,12 @@ enum TaskState { RUNNING, PAUSED, SUCCESS, CANCELED, ERROR } /// Given an AppJSImp, return the Storage instance. Storage getStorageInstance([App? app, String? bucket]) { - firebase_interop.AppStorageJsImpl appImpl = - app != null ? firebase_interop.app(app.name) : firebase_interop.app(); + core_interop.App appImpl = + app != null ? core_interop.app(app.name) : core_interop.app(); - return Storage.getInstance( - bucket != null ? appImpl.storage(bucket) : appImpl.storage()); + return Storage.getInstance(bucket != null + ? storage_interop.getStorage(appImpl.jsObject, bucket) + : storage_interop.getStorage(appImpl.jsObject)); } /// A service for uploading and downloading large objects to and from the @@ -57,25 +59,28 @@ class Storage extends JsObjectWrapper { /// Returns a [StorageReference] for the given [path] in the default bucket. StorageReference ref([String? path]) => - StorageReference.getInstance(jsObject.ref(path)); + StorageReference.getInstance(storage_interop.ref(jsObject, path)); /// Returns a [StorageReference] for the given absolute [url]. StorageReference refFromURL(String url) => - StorageReference.getInstance(jsObject.refFromURL(url)); + StorageReference.getInstance(storage_interop.ref(jsObject, url)); /// Sets the maximum operation retry time to a value of [time]. - void setMaxOperationRetryTime(int time) => - jsObject.setMaxOperationRetryTime(time); + set maxOperationRetryTime(int time) { + jsObject.maxOperationRetryTime = time; + } /// Sets the maximum upload retry time to a value of [time]. - void setMaxUploadRetryTime(int time) => jsObject.setMaxUploadRetryTime(time); + set maxUploadRetryTime(int time) { + jsObject.maxUploadRetryTime = time; + } /// Configures the Storage instance to work with a local emulator. /// /// Note: must be called before using storage methods, do not use /// with production credentials as local connections are unencrypted void useStorageEmulator(String host, int port) => - jsObject.useEmulator(host, port); + storage_interop.connectStorageEmulator(jsObject, host, port); } /// StorageReference is a reference to a Google Cloud Storage object. @@ -118,20 +123,22 @@ class StorageReference /// Returns a child StorageReference to a relative [path] /// from the actual reference. StorageReference child(String path) => - StorageReference.getInstance(jsObject.child(path)); + StorageReference.getInstance(storage_interop.ref(jsObject, path)); /// Deletes the object at the actual location. - Future delete() => handleThenable(jsObject.delete()); + Future delete() => handleThenable(storage_interop.deleteObject(jsObject)); /// Returns a long lived download URL for this reference. Future getDownloadURL() async { - var uriString = await handleThenable(jsObject.getDownloadURL()); + var uriString = + await handleThenable(storage_interop.getDownloadURL(jsObject)); return Uri.parse(uriString); } /// Returns a [FullMetadata] from this reference at actual location. Future getMetadata() => - handleThenable(jsObject.getMetadata()).then(FullMetadata.getInstance); + handleThenable(storage_interop.getMetadata(jsObject)) + .then(FullMetadata.getInstance); /// List items (files) and prefixes (folders) under this storage reference. /// List API is only available for Firebase Storage Rules Version 2. @@ -144,7 +151,7 @@ class StorageReference /// Firebase Storage List API will filter these unsupported objects. /// [list()] may fail if there are too many unsupported objects in the bucket. Future list(ListOptions? options) => - handleThenable(jsObject.list(options?.jsObject)) + handleThenable(storage_interop.list(jsObject, options?.jsObject)) .then(ListResult.getInstance); /// List all items (files) and prefixes (folders) under this storage reference. @@ -159,7 +166,8 @@ class StorageReference /// Warning: [listAll] may potentially consume too many resources if there are /// too many results. Future listAll() => - handleThenable(jsObject.listAll()).then(ListResult.getInstance); + handleThenable(storage_interop.listAll(jsObject)) + .then(ListResult.getInstance); /// Uploads data [blob] to the actual location with optional [metadata]. /// Returns the [UploadTask] which can be used to monitor and manage @@ -167,29 +175,10 @@ class StorageReference UploadTask put(dynamic blob, [UploadMetadata? metadata]) { storage_interop.UploadTaskJsImpl taskImpl; if (metadata != null) { - taskImpl = jsObject.put(blob, metadata.jsObject); - } else { - taskImpl = jsObject.put(blob); - } - return UploadTask.getInstance(taskImpl); - } - - /// Uploads String [data] to the actual location with optional String [format] - /// and [metadata]. - /// - /// See allowed [format] values in [storage_interop.StringFormat] class. - /// - /// Returns the [UploadTask] which can be used to monitor and manage - /// the upload. - UploadTask putString(String data, - [String? format, UploadMetadata? metadata]) { - storage_interop.UploadTaskJsImpl taskImpl; - if (metadata != null) { - taskImpl = jsObject.putString(data, format, metadata.jsObject); - } else if (format != null) { - taskImpl = jsObject.putString(data, format); + taskImpl = storage_interop.uploadBytesResumable( + jsObject, blob, metadata.jsObject); } else { - taskImpl = jsObject.putString(data); + taskImpl = storage_interop.uploadBytesResumable(jsObject, blob); } return UploadTask.getInstance(taskImpl); } @@ -201,7 +190,8 @@ class StorageReference /// Updates metadata from this reference at actual location with /// the new [metadata]. Future updateMetadata(SettableMetadata metadata) async { - await handleThenable(jsObject.updateMetadata(metadata.jsObject)); + await handleThenable( + storage_interop.updateMetadata(jsObject, metadata.jsObject)); return getMetadata(); } } diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart index 42cdbda99b8a..6b9a0f936669 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/interop/storage_interop.dart @@ -5,13 +5,66 @@ // ignore_for_file: avoid_unused_constructor_parameters, non_constant_identifier_names, public_member_api_docs -@JS('firebase.storage') +@JS('firebase_storage') library firebase.storage_interop; import 'package:firebase_core_web/firebase_core_web_interop.dart'; import 'package:js/js.dart'; -@JS('Storage') +@JS() +external StorageJsImpl getStorage([AppJsImpl? app, String? bucketUrl]); + +@JS() +external void connectStorageEmulator( + StorageJsImpl storage, String host, int port, + [EmulatorOptions? options]); + +@JS() +external PromiseJsImpl deleteObject(ReferenceJsImpl ref); + +@JS() +external PromiseJsImpl getDownloadURL(ReferenceJsImpl ref); + +@JS() +external PromiseJsImpl getBlob(ReferenceJsImpl ref, + [int? maxDownloadSizeBytes]); + +@JS() +external PromiseJsImpl> getBytes(ReferenceJsImpl ref, + [int? maxDownloadSizeBytes]); + +@JS() +external PromiseJsImpl getMetadata(ReferenceJsImpl ref); + +@JS() +external PromiseJsImpl list(ReferenceJsImpl ref, + [ListOptionsJsImpl? listOptions]); + +@JS() +external PromiseJsImpl listAll(ReferenceJsImpl ref); + +@JS() +/* if 2nd arg is `url`, first arg has to be StorageJsImpl */ +/* if 2nd arg is `path`, first arg can be StorageJsImpl || ReferenceJsImpl */ +external ReferenceJsImpl ref(Object storageOrRef, [String? urlOrPath]); + +@JS() +external PromiseJsImpl updateMetadata( + ReferenceJsImpl ref, SettableMetadataJsImpl settableMetadata); + +@JS() +external UploadTaskJsImpl uploadBytesResumable( + ReferenceJsImpl ref, dynamic /* Blob | Uint8Array | ArrayBuffer */ data, + [UploadMetadataJsImpl? metadata]); + +@JS() +@anonymous +class EmulatorOptions { + external factory EmulatorOptions({mockUserToken}); + external String get mockUserToken; +} + +@JS('FirebaseStorage') abstract class StorageJsImpl { external AppJsImpl get app; external set app(AppJsImpl a); @@ -19,14 +72,9 @@ abstract class StorageJsImpl { external set maxOperationRetryTime(int t); external int get maxUploadRetryTime; external set maxUploadRetryTime(int t); - external ReferenceJsImpl ref([String? path]); - external ReferenceJsImpl refFromURL(String url); - external void setMaxOperationRetryTime(int time); - external void setMaxUploadRetryTime(int time); - external void useEmulator(String host, int port); } -@JS('Reference') +@JS('StorageReference') abstract class ReferenceJsImpl { external String get bucket; external set bucket(String s); @@ -40,19 +88,9 @@ abstract class ReferenceJsImpl { external set root(ReferenceJsImpl r); external StorageJsImpl get storage; external set storage(StorageJsImpl s); - external ReferenceJsImpl child(String path); - external PromiseJsImpl delete(); - external PromiseJsImpl getDownloadURL(); - external PromiseJsImpl getMetadata(); - external PromiseJsImpl list([ListOptionsJsImpl? options]); - external PromiseJsImpl listAll(); - external UploadTaskJsImpl put(dynamic blob, [UploadMetadataJsImpl? metadata]); - external UploadTaskJsImpl putString(String value, - [String? format, UploadMetadataJsImpl? metadata]); + @override external String toString(); - external PromiseJsImpl updateMetadata( - SettableMetadataJsImpl metadata); } //@JS('FullMetadata') @@ -69,6 +107,10 @@ class FullMetadataJsImpl extends UploadMetadataJsImpl { dynamic customMetadata}); external String get bucket; + // TODO - new API. + external List? get downloadTokens; + // TODO - new API. + external ReferenceJsImpl? get ref; external String? get fullPath; external String? get generation; external String? get metageneration; diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart b/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart index da69edc853dd..764a40d72168 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/reference_web.dart @@ -3,6 +3,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +import 'dart:convert'; import 'dart:html' as html; import 'dart:typed_data'; @@ -185,13 +186,21 @@ class ReferenceWeb extends ReferencePlatform { PutStringFormat format, [ SettableMetadata? metadata, ]) { + dynamic _data = data; + + // The universal package is converting raw to base64, so we need to convert + // Any base64 string values into a Uint8List. + if (format == PutStringFormat.base64) { + _data = base64Decode(data); + } + return TaskWeb( this, - _ref.putString( - data, - putStringFormatToString(format), + _ref.put( + _data, settableMetadataToFbUploadMetadata( _cache.store(metadata), + // md5 is computed server-side, so we don't have to unpack a potentially huge Blob. ), ), ); diff --git a/packages/firebase_storage/firebase_storage_web/lib/src/utils/metadata.dart b/packages/firebase_storage/firebase_storage_web/lib/src/utils/metadata.dart index 00d639f9db9c..655e6c518bad 100644 --- a/packages/firebase_storage/firebase_storage_web/lib/src/utils/metadata.dart +++ b/packages/firebase_storage/firebase_storage_web/lib/src/utils/metadata.dart @@ -4,6 +4,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:firebase_storage_platform_interface/firebase_storage_platform_interface.dart'; + import '../interop/storage.dart' as storage_interop; /// Converts FullMetadata coming from the JS Interop layer to FullMetadata for the plugin. diff --git a/tests/test_driver/firebase_storage/reference_e2e.dart b/tests/test_driver/firebase_storage/reference_e2e.dart index 69071fd2675b..c4c065b92533 100644 --- a/tests/test_driver/firebase_storage/reference_e2e.dart +++ b/tests/test_driver/firebase_storage/reference_e2e.dart @@ -2,9 +2,9 @@ import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; +import 'package:drive/drive.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/foundation.dart'; -import 'package:drive/drive.dart'; import './test_utils.dart';