@@ -33,6 +33,18 @@ namespace firebase {
3333namespace storage {
3434namespace internal {
3535
36+ // clang-format off
37+ #define LIST_RESULT_METHODS (X ) \
38+ X (GetPrefixes, " getPrefixes" , " ()Ljava/util/List;" ), \
39+ X (GetItems, " getItems" , " ()Ljava/util/List;" ), \
40+ X (GetPageToken, " getPageToken" , " ()Ljava/lang/String;" )
41+ METHOD_LOOKUP_DECLARATION (list_result, LIST_RESULT_METHODS )
42+ METHOD_LOOKUP_DEFINITION (list_result,
43+ PROGUARD_KEEP_CLASS
44+ " com/google/firebase/storage/ListResult" ,
45+ LIST_RESULT_METHODS )
46+ // clang-format on
47+
3648// clang-format off
3749#define STORAGE_REFERENCE_METHODS (X ) \
3850 X (Child, " child" , \
@@ -61,6 +73,8 @@ namespace internal {
6173 X (PutFileWithMetadata, " putFile" , \
6274 " (Landroid/net/Uri;Lcom/google/firebase/storage/StorageMetadata;)" \
6375 " Lcom/google/firebase/storage/UploadTask;" ), \
76+ X (List, " list" , \
77+ " (ILjava/lang/String;)Lcom/google/android/gms/tasks/Task;" ), \
6478 X (PutFileWithMetadataAndUri, " putFile" , \
6579 " (Landroid/net/Uri;Lcom/google/firebase/storage/StorageMetadata;" \
6680 " Landroid/net/Uri;)Lcom/google/firebase/storage/UploadTask;" ), \
@@ -105,17 +119,20 @@ enum StorageReferenceFn {
105119 kStorageReferenceFnUpdateMetadata ,
106120 kStorageReferenceFnPutBytes ,
107121 kStorageReferenceFnPutFile ,
122+ kStorageReferenceFnList ,
108123 kStorageReferenceFnCount ,
109124};
110125
111126bool StorageReferenceInternal::Initialize (App* app) {
112127 JNIEnv* env = app->GetJNIEnv ();
113128 jobject activity = app->activity ();
114- return storage_reference::CacheMethodIds (env, activity);
129+ return list_result::CacheMethodIds (env, activity) &&
130+ storage_reference::CacheMethodIds (env, activity);
115131}
116132
117133void StorageReferenceInternal::Terminate (App* app) {
118134 JNIEnv* env = app->GetJNIEnv ();
135+ list_result::ReleaseClass (env);
119136 storage_reference::ReleaseClass (env);
120137 util::CheckAndClearJniExceptions (env);
121138}
@@ -249,9 +266,59 @@ void StorageReferenceInternal::FutureCallback(JNIEnv* env, jobject result,
249266 // is returned.
250267 data->impl ->CompleteWithResult (data->handle , code, message.c_str (),
251268 Metadata (nullptr ));
269+ } else if (data->func == kStorageReferenceFnList ) {
270+ data->impl ->CompleteWithResult (data->handle , code, message.c_str (),
271+ StorageListResult (nullptr ));
252272 } else {
253273 data->impl ->Complete (data->handle , code, message.c_str ());
254274 }
275+ } else if (result && env->IsInstanceOf (result, list_result::GetClass ())) {
276+ // result is a ListResult.
277+ SafeFutureHandle<StorageListResult> handle (data->handle );
278+ jobject prefixes_list = env->CallObjectMethod (
279+ result, list_result::GetMethodId (list_result::kGetPrefixes ));
280+ jobject items_list = env->CallObjectMethod (
281+ result, list_result::GetMethodId (list_result::kGetItems ));
282+ jstring page_token_jstring = static_cast <jstring>(env->CallObjectMethod (
283+ result, list_result::GetMethodId (list_result::kGetPageToken )));
284+
285+ std::vector<StorageReference> prefixes;
286+ if (prefixes_list) {
287+ jint size = env->CallIntMethod (
288+ prefixes_list, list::GetMethodId (list::kSize ));
289+ for (jint i = 0 ; i < size; ++i) {
290+ jobject prefix_obj = env->CallObjectMethod (
291+ prefixes_list, list::GetMethodId (list::kGet ), i);
292+ prefixes.push_back (
293+ StorageReference (new StorageReferenceInternal (data->storage , prefix_obj)));
294+ env->DeleteLocalRef (prefix_obj);
295+ }
296+ env->DeleteLocalRef (prefixes_list);
297+ }
298+
299+ std::vector<StorageReference> items;
300+ if (items_list) {
301+ jint size = env->CallIntMethod (
302+ items_list, list::GetMethodId (list::kSize ));
303+ for (jint i = 0 ; i < size; ++i) {
304+ jobject item_obj = env->CallObjectMethod (
305+ items_list, list::GetMethodId (list::kGet ), i);
306+ items.push_back (
307+ StorageReference (new StorageReferenceInternal (data->storage , item_obj)));
308+ env->DeleteLocalRef (item_obj);
309+ }
310+ env->DeleteLocalRef (items_list);
311+ }
312+
313+ std::string page_token;
314+ if (page_token_jstring) {
315+ page_token = util::JniStringToString (env, page_token_jstring);
316+ env->DeleteLocalRef (page_token_jstring);
317+ }
318+
319+ StorageListResultInternal* list_internal =
320+ new StorageListResultInternal (prefixes, items, page_token);
321+ data->impl ->CompleteWithResult (handle, kErrorNone , StorageListResult (list_internal));
255322 } else if (result && env->IsInstanceOf (result, util::string::GetClass ())) {
256323 LogDebug (" FutureCallback: Completing a Future from a String." );
257324 // Complete a Future<std::string> from a Java String object.
@@ -687,6 +754,38 @@ Future<Metadata> StorageReferenceInternal::PutFileLastResult() {
687754 future ()->LastResult (kStorageReferenceFnPutFile ));
688755}
689756
757+ Future<StorageListResult> StorageReferenceInternal::List (int max_results_per_page,
758+ const char *page_token) {
759+ JNIEnv* env = storage_->app ()->GetJNIEnv ();
760+ ReferenceCountedFutureImpl* future_impl = future ();
761+ FutureHandle handle =
762+ future_impl->Alloc <StorageListResult>(kStorageReferenceFnList );
763+
764+ jstring java_page_token = page_token ? env->NewStringUTF (page_token) : nullptr ;
765+ jobject task = env->CallObjectMethod (
766+ obj_, storage_reference::GetMethodId (storage_reference::kList ),
767+ max_results_per_page, java_page_token);
768+
769+ if (java_page_token) {
770+ env->DeleteLocalRef (java_page_token);
771+ }
772+
773+ util::RegisterCallbackOnTask (
774+ env, task, FutureCallback,
775+ // FutureCallback will delete the newed FutureCallbackData.
776+ reinterpret_cast <void *>(new FutureCallbackData (handle, future (), storage_,
777+ kStorageReferenceFnList )),
778+ storage_->jni_task_id ());
779+ util::CheckAndClearJniExceptions (env);
780+ env->DeleteLocalRef (task);
781+ return ListLastResult ();
782+ }
783+
784+ Future<StorageListResult> StorageReferenceInternal::ListLastResult () {
785+ return static_cast <const Future<StorageListResult>&>(
786+ future ()->LastResult (kStorageReferenceFnList ));
787+ }
788+
690789ReferenceCountedFutureImpl* StorageReferenceInternal::future () {
691790 return storage_->future_manager ().GetFutureApi (this );
692791}
0 commit comments