in storage/src/android/storage_reference_android.cc [225:339]
void StorageReferenceInternal::FutureCallback(JNIEnv* env, jobject result,
util::FutureResult result_code,
const char* status_message,
void* callback_data) {
FutureCallbackData* data =
reinterpret_cast<FutureCallbackData*>(callback_data);
if (data == nullptr) {
util::CheckAndClearJniExceptions(env);
return;
}
if (result_code != util::kFutureResultSuccess) {
// Failed, so the result is a StorageException.
std::string message;
Error code =
(result_code == util::kFutureResultCancelled)
? kErrorCancelled
: data->storage->ErrorFromJavaStorageException(result, &message);
LogDebug("FutureCallback: Completing a Future with an error (%d).", code);
if (data->func == kStorageReferenceFnPutFile ||
data->func == kStorageReferenceFnPutBytes ||
data->func == kStorageReferenceFnGetMetadata ||
data->func == kStorageReferenceFnUpdateMetadata) {
// If it's a Future<Metadata> that failed, ensure that an invalid metadata
// is returned.
data->impl->CompleteWithResult(data->handle, code, message.c_str(),
Metadata(nullptr));
} else {
data->impl->Complete(data->handle, code, message.c_str());
}
} else if (result && env->IsInstanceOf(result, util::string::GetClass())) {
LogDebug("FutureCallback: Completing a Future from a String.");
// Complete a Future<std::string> from a Java String object.
data->impl->CompleteWithResult<std::string>(
data->handle, kErrorNone, status_message,
util::JStringToString(env, result));
} else if (result && env->IsInstanceOf(result, util::uri::GetClass())) {
LogDebug("FutureCallback: Completing a Future from a URI.");
// Complete a Future<std::string> from a Java URI object.
data->impl->CompleteWithResult<std::string>(
data->handle, kErrorNone, status_message,
util::JniUriToString(env, env->NewLocalRef(result)));
} else if (result &&
env->IsInstanceOf(
result, stream_download_task_task_snapshot::GetClass()) &&
data->dest != nullptr) {
// Complete a Future<size_t>. We have previously also copied
// bytes from a Java byte[] array via CppByteDownloader.
LogDebug("FutureCallback: Completing a Future from a byte array.");
jlong num_bytes = env->CallLongMethod(
result, stream_download_task_task_snapshot::GetMethodId(
stream_download_task_task_snapshot::kGetBytesTransferred));
data->impl->Complete<size_t>(
data->handle, kErrorNone, status_message,
[num_bytes](size_t* size) { *size = num_bytes; });
} else if (result &&
env->IsInstanceOf(result, storage_metadata::GetClass())) {
// Complete a Future<Metadata> from a Java StorageMetadata object.
LogDebug("FutureCallback: Completing a Future from a StorageMetadata.");
data->impl->Complete<Metadata>(
data->handle, kErrorNone, status_message,
[data, result](Metadata* metadata) {
*metadata = Metadata(new MetadataInternal(data->storage, result));
});
} else if (result &&
env->IsInstanceOf(result, upload_task_task_snapshot::GetClass())) {
LogDebug("FutureCallback: Completing a Future from an UploadTask.");
// Complete a Future<Metadata> from a Java UploadTask.TaskSnapshot.
jobject metadata_obj = env->CallObjectMethod(
result, upload_task_task_snapshot::GetMethodId(
upload_task_task_snapshot::kGetMetadata));
data->impl->Complete<Metadata>(data->handle, kErrorNone, status_message,
[data, metadata_obj](Metadata* metadata) {
*metadata = Metadata(new MetadataInternal(
data->storage, metadata_obj));
});
env->DeleteLocalRef(metadata_obj);
} else if (result &&
env->IsInstanceOf(result,
file_download_task_task_snapshot::GetClass())) {
LogDebug("FutureCallback: Completing a Future from a FileDownloadTask.");
// Complete a Future<size_t> from a Java FileDownloadTask.TaskSnapshot.
jlong bytes = env->CallLongMethod(
result, file_download_task_task_snapshot::GetMethodId(
file_download_task_task_snapshot::kGetBytesTransferred));
data->impl->Complete<size_t>(data->handle, kErrorNone, status_message,
[bytes](size_t* size) { *size = bytes; });
} else {
LogDebug("FutureCallback: Completing a Future from a default result.");
// Unknown or null result type, treat this as a Future<void> and just
// return success.
data->impl->Complete(data->handle, kErrorNone, status_message);
}
if (data->listener != nullptr) {
env->CallVoidMethod(data->listener,
cpp_storage_listener::GetMethodId(
cpp_storage_listener::kDiscardPointers));
env->DeleteGlobalRef(data->listener);
}
if (data->cpp_byte_downloader != nullptr) {
env->CallVoidMethod(data->cpp_byte_downloader,
cpp_byte_downloader::GetMethodId(
cpp_byte_downloader::kDiscardPointers));
env->DeleteGlobalRef(data->cpp_byte_downloader);
}
if (data->cpp_byte_uploader != nullptr) {
env->CallVoidMethod(
data->cpp_byte_uploader,
cpp_byte_uploader::GetMethodId(cpp_byte_uploader::kDiscardPointers));
env->DeleteGlobalRef(data->cpp_byte_uploader);
}
delete data;
util::CheckAndClearJniExceptions(env);
}