diff --git a/native/android/app/CMakeLists.txt b/native/android/app/CMakeLists.txt --- a/native/android/app/CMakeLists.txt +++ b/native/android/app/CMakeLists.txt @@ -121,6 +121,7 @@ "./src/cpp/NotificationsCryptoModuleJNIHelper.cpp" "./src/cpp/StaffUtilsJNIHelper.cpp" "./src/cpp/AESCrypto.cpp" + "./src/cpp/CommServicesAuthMetadataEmitter.cpp" ) list(APPEND GENERATED_NATIVE_CODE diff --git a/native/android/app/src/cpp/CommServicesAuthMetadataEmitter.cpp b/native/android/app/src/cpp/CommServicesAuthMetadataEmitter.cpp new file mode 100644 --- /dev/null +++ b/native/android/app/src/cpp/CommServicesAuthMetadataEmitter.cpp @@ -0,0 +1,32 @@ +#include "jniHelpers.h" +#include +#include + +using namespace facebook::jni; + +class CommServicesAuthMetadataEmitterJavaClass + : public JavaClass { +public: + static auto constexpr kJavaDescriptor = + "Lapp/comm/android/commservices/CommServicesAuthMetadataEmitter;"; + + static void + sendAuthMetadataToJS(rust::String accessToken, rust::String userID) { + + static const auto cls = javaClassStatic(); + static auto method = cls->getStaticMethod( + "sendAuthMetadataToJS"); + method(cls, std::string(accessToken), std::string(userID)); + } +}; + +namespace comm { +void CommServicesAuthMetadataEmitter::sendAuthMetadataToJS( + rust::String accessToken, + rust::String userID) { + NativeAndroidAccessProvider::runTask([&]() { + CommServicesAuthMetadataEmitterJavaClass::sendAuthMetadataToJS( + accessToken, userID); + }); +} +} // namespace comm diff --git a/native/android/app/src/main/java/app/comm/android/MainApplication.java b/native/android/app/src/main/java/app/comm/android/MainApplication.java --- a/native/android/app/src/main/java/app/comm/android/MainApplication.java +++ b/native/android/app/src/main/java/app/comm/android/MainApplication.java @@ -5,6 +5,7 @@ import android.database.CursorWindow; import androidx.annotation.NonNull; import androidx.multidex.MultiDexApplication; +import app.comm.android.commservices.CommServicesPackage; import app.comm.android.fbjni.CommSecureStore; import app.comm.android.fbjni.DatabaseInitializer; import app.comm.android.fbjni.GlobalDBSingleton; @@ -49,6 +50,7 @@ List packages = new PackageList(this).getPackages(); packages.add(new KeyboardInputPackage(this.getApplication())); packages.add(new CommAndroidNotificationsPackage()); + packages.add(new CommServicesPackage()); return packages; } diff --git a/native/android/app/src/main/java/app/comm/android/commservices/CommServicesAuthMetadataEmitter.java b/native/android/app/src/main/java/app/comm/android/commservices/CommServicesAuthMetadataEmitter.java new file mode 100644 --- /dev/null +++ b/native/android/app/src/main/java/app/comm/android/commservices/CommServicesAuthMetadataEmitter.java @@ -0,0 +1,76 @@ +package app.comm.android.commservices; + +import android.util.Log; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.modules.core.DeviceEventManagerModule; +import java.util.HashMap; +import java.util.Map; + +public class CommServicesAuthMetadataEmitter + extends ReactContextBaseJavaModule { + + private static int listenersCount = 0; + private static CommServicesAuthMetadataEmitter sharedInstance = null; + + public static final String COMM_SERVICES_AUTH_METADATA = + "commServicesAuthMetadata"; + + CommServicesAuthMetadataEmitter(ReactApplicationContext reactContext) { + super(reactContext); + } + + @Override + public String getName() { + return "CommServicesAuthMetadataEmitter"; + } + + @ReactMethod + public void addListener(String eventName) { + synchronized (CommServicesAuthMetadataEmitter.class) { + listenersCount++; + if (sharedInstance == null) { + sharedInstance = this; + } + } + } + + @ReactMethod + public void removeListeners(Integer count) { + synchronized (CommServicesAuthMetadataEmitter.class) { + listenersCount -= count; + boolean isLastListener = listenersCount == 0; + if (isLastListener) { + sharedInstance = null; + } + } + } + + public static void sendAuthMetadataToJS(String accessToken, String userID) { + synchronized (CommServicesAuthMetadataEmitter.class) { + if (sharedInstance == null) { + return; + } + + // Event body must match UserLoginResponse + // type from 'lib/types/identity-service-types.js' + WritableMap eventBody = Arguments.createMap(); + eventBody.putString("accessToken", accessToken); + eventBody.putString("userID", userID); + + sharedInstance.getReactApplicationContext() + .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class) + .emit(COMM_SERVICES_AUTH_METADATA, eventBody); + } + } + + @Override + public Map getConstants() { + final Map constants = new HashMap<>(); + constants.put("COMM_SERVICES_AUTH_METADATA", COMM_SERVICES_AUTH_METADATA); + return constants; + } +} diff --git a/native/android/app/src/main/java/app/comm/android/commservices/CommServicesPackage.java b/native/android/app/src/main/java/app/comm/android/commservices/CommServicesPackage.java new file mode 100644 --- /dev/null +++ b/native/android/app/src/main/java/app/comm/android/commservices/CommServicesPackage.java @@ -0,0 +1,27 @@ +package app.comm.android.commservices; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CommServicesPackage implements ReactPackage { + @Override + public List + createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List + createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + + modules.add(new CommServicesAuthMetadataEmitter(reactContext)); + + return modules; + } +}