@onekeyfe/react-native-jpush 0.0.0-stage → 6.7.0-22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +56 -2
- package/ReactNativeJpush.podspec +66 -0
- package/android/CMakeLists.txt +24 -0
- package/android/build.gradle +144 -0
- package/android/fcm/build.gradle +36 -0
- package/android/fcm/consumer-rules.pro +2 -0
- package/android/fcm/src/main/AndroidManifest.xml +25 -0
- package/android/fcm/src/main/java/com/onekey/jpush/fcm/FcmInitProvider.java +25 -0
- package/android/fcm/src/main/java/com/onekey/jpush/fcm/FcmMessagingService.java +84 -0
- package/android/fcm/src/main/java/com/onekey/jpush/fcm/FcmPushManager.java +69 -0
- package/android/fcm/src/test/java/com/onekey/jpush/fcm/FcmAdapterTest.java +684 -0
- package/android/fcm/src/test/java/com/onekey/jpush/fcm/FcmManifestTest.java +54 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +143 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/cn/android/service/JTransitActivity.java +19 -0
- package/android/src/main/java/cn/jiguang/android/BuildConfig.java +10 -0
- package/android/src/main/java/cn/jiguang/android/IDataShare.java +190 -0
- package/android/src/main/java/cn/jiguang/api/BaseLogger.java +82 -0
- package/android/src/main/java/cn/jiguang/api/JAction.java +22 -0
- package/android/src/main/java/cn/jiguang/api/JActionExtra.java +21 -0
- package/android/src/main/java/cn/jiguang/api/JAnalyticsAction.java +11 -0
- package/android/src/main/java/cn/jiguang/api/JCoreInterface.java +228 -0
- package/android/src/main/java/cn/jiguang/api/JCoreManager.java +156 -0
- package/android/src/main/java/cn/jiguang/api/JDispatchAction.java +66 -0
- package/android/src/main/java/cn/jiguang/api/MultiSpHelper.java +114 -0
- package/android/src/main/java/cn/jiguang/api/ReportCallBack.java +9 -0
- package/android/src/main/java/cn/jiguang/api/SdkType.java +13 -0
- package/android/src/main/java/cn/jiguang/api/utils/JCollectionAuth.java +28 -0
- package/android/src/main/java/cn/jiguang/core/JCoreCrypto.java +545 -0
- package/android/src/main/java/cn/jiguang/core/JCoreStorage.java +737 -0
- package/android/src/main/java/cn/jiguang/core/JCoreTcpEngine.java +1395 -0
- package/android/src/main/java/cn/jiguang/core/JCoreWireCodec.java +1716 -0
- package/android/src/main/java/cn/jiguang/internal/ActionManager.java +63 -0
- package/android/src/main/java/cn/jiguang/internal/JConstants.java +61 -0
- package/android/src/main/java/cn/jiguang/internal/JCoreHelperAction.java +12 -0
- package/android/src/main/java/cn/jiguang/internal/JCoreInternalHelper.java +102 -0
- package/android/src/main/java/cn/jiguang/net/DefaultHostVerifier.java +40 -0
- package/android/src/main/java/cn/jiguang/net/HttpRequest.java +78 -0
- package/android/src/main/java/cn/jiguang/net/HttpResponse.java +48 -0
- package/android/src/main/java/cn/jiguang/net/HttpUtils.java +106 -0
- package/android/src/main/java/cn/jiguang/plugins/core/JCoreModule.java +91 -0
- package/android/src/main/java/cn/jiguang/plugins/core/JCorePackage.java +27 -0
- package/android/src/main/java/cn/jiguang/plugins/push/JPushModule.java +773 -0
- package/android/src/main/java/cn/jiguang/plugins/push/JPushPackage.java +25 -0
- package/android/src/main/java/cn/jiguang/plugins/push/common/JConstants.java +88 -0
- package/android/src/main/java/cn/jiguang/plugins/push/common/JLogger.java +122 -0
- package/android/src/main/java/cn/jiguang/plugins/push/helper/JPushHelper.java +710 -0
- package/android/src/main/java/cn/jiguang/plugins/push/receiver/JPushBroadcastReceiver.java +37 -0
- package/android/src/main/java/cn/jiguang/plugins/push/receiver/JPushModuleReceiver.java +264 -0
- package/android/src/main/java/cn/jiguang/plugins/service/JCoreModuleService.java +7 -0
- package/android/src/main/java/cn/jpush/android/api/BasicPushNotificationBuilder.java +83 -0
- package/android/src/main/java/cn/jpush/android/api/CallBackParams.java +50 -0
- package/android/src/main/java/cn/jpush/android/api/CmdMessage.java +33 -0
- package/android/src/main/java/cn/jpush/android/api/CustomMessage.java +28 -0
- package/android/src/main/java/cn/jpush/android/api/CustomPushNotificationBuilder.java +81 -0
- package/android/src/main/java/cn/jpush/android/api/DefaultPushNotificationBuilder.java +90 -0
- package/android/src/main/java/cn/jpush/android/api/InAppSlotParams.java +65 -0
- package/android/src/main/java/cn/jpush/android/api/InstrumentedActivity.java +17 -0
- package/android/src/main/java/cn/jpush/android/api/InstrumentedListActivity.java +17 -0
- package/android/src/main/java/cn/jpush/android/api/JPushInterface.java +490 -0
- package/android/src/main/java/cn/jpush/android/api/JPushMessage.java +121 -0
- package/android/src/main/java/cn/jpush/android/api/JThirdPlatFormInterface.java +247 -0
- package/android/src/main/java/cn/jpush/android/api/MultiActionsNotificationBuilder.java +72 -0
- package/android/src/main/java/cn/jpush/android/api/NotificationCustomButton.java +50 -0
- package/android/src/main/java/cn/jpush/android/api/NotificationMessage.java +67 -0
- package/android/src/main/java/cn/jpush/android/api/PushNotificationBuilder.java +13 -0
- package/android/src/main/java/cn/jpush/android/api/TagAliasCallback.java +8 -0
- package/android/src/main/java/cn/jpush/android/data/JPushCollectControl.java +96 -0
- package/android/src/main/java/cn/jpush/android/data/JPushConfig.java +79 -0
- package/android/src/main/java/cn/jpush/android/data/JPushConfigEx.java +41 -0
- package/android/src/main/java/cn/jpush/android/data/JPushLocalNotification.java +155 -0
- package/android/src/main/java/cn/jpush/android/helper/JCoreHelper.java +70 -0
- package/android/src/main/java/cn/jpush/android/helper/Logger.java +82 -0
- package/android/src/main/java/cn/jpush/android/local/ActionHelper.java +1293 -0
- package/android/src/main/java/cn/jpush/android/local/ActivityLifeCallBack.java +47 -0
- package/android/src/main/java/cn/jpush/android/local/JPushAction.java +67 -0
- package/android/src/main/java/cn/jpush/android/local/JPushConstants.java +34 -0
- package/android/src/main/java/cn/jpush/android/local/JPushResponse.java +26 -0
- package/android/src/main/java/cn/jpush/android/local/ProxyActivityAction.java +34 -0
- package/android/src/main/java/cn/jpush/android/service/AlarmReceiver.java +15 -0
- package/android/src/main/java/cn/jpush/android/service/BActivity.java +19 -0
- package/android/src/main/java/cn/jpush/android/service/DActivity.java +19 -0
- package/android/src/main/java/cn/jpush/android/service/DaemonService.java +17 -0
- package/android/src/main/java/cn/jpush/android/service/DataProvider.java +136 -0
- package/android/src/main/java/cn/jpush/android/service/DataShare.java +129 -0
- package/android/src/main/java/cn/jpush/android/service/DownloadProvider.java +139 -0
- package/android/src/main/java/cn/jpush/android/service/InitProvider.java +48 -0
- package/android/src/main/java/cn/jpush/android/service/JCommonService.java +79 -0
- package/android/src/main/java/cn/jpush/android/service/JNotifyActivity.java +28 -0
- package/android/src/main/java/cn/jpush/android/service/JPushMessageReceiver.java +94 -0
- package/android/src/main/java/cn/jpush/android/service/PushReceiver.java +26 -0
- package/android/src/main/java/cn/jpush/android/service/PushService.java +28 -0
- package/android/src/main/java/cn/jpush/android/service/SchedulerReceiver.java +17 -0
- package/android/src/main/java/cn/jpush/android/service/TagAliasReceiver.java +11 -0
- package/android/src/main/java/cn/jpush/android/service/WakedResultReceiver.java +24 -0
- package/android/src/main/java/cn/jpush/android/ui/FullScreenView.java +11 -0
- package/android/src/main/java/cn/jpush/android/ui/PopWinActivity.java +16 -0
- package/android/src/main/java/cn/jpush/android/ui/PushActivity.java +27 -0
- package/android/src/main/java/cn/jpush/android/ui/RoundedImageView.java +63 -0
- package/android/src/main/java/cn/jpush/android/ui/ShadowViewCard.java +56 -0
- package/android/src/main/java/cn/jpush/android/ups/ICallbackResult.java +5 -0
- package/android/src/main/java/cn/jpush/android/ups/JPushUPSManager.java +37 -0
- package/android/src/main/java/cn/jpush/android/ups/TokenResult.java +47 -0
- package/android/src/main/java/cn/jpush/android/ups/UPSRegisterCallBack.java +4 -0
- package/android/src/main/java/cn/jpush/android/ups/UPSTurnCallBack.java +4 -0
- package/android/src/main/java/cn/jpush/android/ups/UPSUnRegisterCallBack.java +4 -0
- package/android/src/main/java/com/margelo/nitro/reactnativejpush/ReactNativeJpush.kt +455 -0
- package/android/src/main/java/com/margelo/nitro/reactnativejpush/ReactNativeJpushPackage.kt +50 -0
- package/android/src/main/res/values/jpush_string.xml +7 -0
- package/android/src/main/res/values/jpush_style.xml +22 -0
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/JPushCloudHandshakeTest.java +110 -0
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/JPushHandshakeFailureTest.java +73 -0
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/ReactNativeJpushProtocolTest.java +908 -0
- package/ios/ReactNativeJpush.swift +522 -0
- package/ios/bridge/RCTJCoreModule.h +5 -0
- package/ios/bridge/RCTJCoreModule.m +31 -0
- package/ios/bridge/RCTJPushEventQueue.h +14 -0
- package/ios/bridge/RCTJPushEventQueue.m +23 -0
- package/ios/bridge/RCTJPushModule.h +37 -0
- package/ios/bridge/RCTJPushModule.m +1165 -0
- package/ios/include/JCOREService.h +3 -0
- package/ios/include/JGCOREAPI.h +14 -0
- package/ios/include/JGInforCollectionAuth.h +17 -0
- package/ios/include/JGInforCollectionAuthItems.h +2 -0
- package/ios/include/JGPushNotificationTrigger.h +2 -0
- package/ios/include/JPUSHService.h +359 -0
- package/ios/jcore/JCOREConfiguration.h +141 -0
- package/ios/jcore/JCOREConfiguration.m +703 -0
- package/ios/jcore/JCORECrypto.h +73 -0
- package/ios/jcore/JCORECrypto.m +649 -0
- package/ios/jcore/JCORESisResolver.h +56 -0
- package/ios/jcore/JCORESisResolver.m +525 -0
- package/ios/jcore/JCORETcpSession.h +42 -0
- package/ios/jcore/JCORETcpSession.m +956 -0
- package/ios/jcore/JCOREWireProtocol.h +274 -0
- package/ios/jcore/JCOREWireProtocol.m +1453 -0
- package/ios/jpush/JPUSHModels.m +214 -0
- package/ios/jpush/JPUSHNotificationManager.h +34 -0
- package/ios/jpush/JPUSHNotificationManager.m +360 -0
- package/ios/jpush/JPUSHService.m +794 -0
- package/ios/tests/ReactNativeJpushTests.m +148 -0
- package/lib/module/ReactNativeJpush.nitro.js +4 -0
- package/lib/module/ReactNativeJpush.nitro.js.map +1 -0
- package/lib/module/index.js +801 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/ReactNativeJpush.nitro.d.ts +60 -0
- package/lib/typescript/src/ReactNativeJpush.nitro.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +235 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/nitro.json +23 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string_std__string.hpp +76 -0
- package/nitrogen/generated/android/c++/JHybridReactNativeJpushSpec.cpp +310 -0
- package/nitrogen/generated/android/c++/JHybridReactNativeJpushSpec.hpp +115 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativejpush/Func_void_bool.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativejpush/Func_void_std__string_std__string.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativejpush/HybridReactNativeJpushSpec.kt +274 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativejpush/reactnativejpushOnLoad.kt +35 -0
- package/nitrogen/generated/android/reactnativejpush+autolinking.cmake +81 -0
- package/nitrogen/generated/android/reactnativejpush+autolinking.gradle +27 -0
- package/nitrogen/generated/android/reactnativejpushOnLoad.cpp +58 -0
- package/nitrogen/generated/android/reactnativejpushOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/ReactNativeJpush+autolinking.rb +62 -0
- package/nitrogen/generated/ios/ReactNativeJpush-Swift-Cxx-Bridge.cpp +49 -0
- package/nitrogen/generated/ios/ReactNativeJpush-Swift-Cxx-Bridge.hpp +147 -0
- package/nitrogen/generated/ios/ReactNativeJpush-Swift-Cxx-Umbrella.hpp +46 -0
- package/nitrogen/generated/ios/ReactNativeJpushAutolinking.mm +33 -0
- package/nitrogen/generated/ios/ReactNativeJpushAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridReactNativeJpushSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridReactNativeJpushSpecSwift.hpp +402 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string_std__string.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridReactNativeJpushSpec.swift +107 -0
- package/nitrogen/generated/ios/swift/HybridReactNativeJpushSpec_cxx.swift +723 -0
- package/nitrogen/generated/shared/c++/HybridReactNativeJpushSpec.cpp +73 -0
- package/nitrogen/generated/shared/c++/HybridReactNativeJpushSpec.hpp +116 -0
- package/package.json +174 -4
- package/src/ReactNativeJpush.nitro.ts +93 -0
- package/src/index.tsx +1090 -0
|
@@ -0,0 +1,684 @@
|
|
|
1
|
+
package com.onekey.jpush.fcm;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.*;
|
|
4
|
+
import static org.mockito.ArgumentMatchers.*;
|
|
5
|
+
import static org.mockito.Mockito.*;
|
|
6
|
+
|
|
7
|
+
import android.app.ActivityManager;
|
|
8
|
+
import android.app.KeyguardManager;
|
|
9
|
+
import android.app.Notification;
|
|
10
|
+
import android.app.NotificationManager;
|
|
11
|
+
import android.content.Context;
|
|
12
|
+
import android.content.Intent;
|
|
13
|
+
import android.content.pm.ActivityInfo;
|
|
14
|
+
import android.content.pm.ApplicationInfo;
|
|
15
|
+
import android.content.pm.ResolveInfo;
|
|
16
|
+
import android.os.Bundle;
|
|
17
|
+
import android.os.Looper;
|
|
18
|
+
import android.os.Process;
|
|
19
|
+
import cn.jiguang.api.JCoreManager;
|
|
20
|
+
import cn.jiguang.api.utils.JCollectionAuth;
|
|
21
|
+
import cn.jiguang.core.JCoreCrypto;
|
|
22
|
+
import cn.jiguang.core.JCoreStorage;
|
|
23
|
+
import cn.jiguang.core.JCoreTcpEngine;
|
|
24
|
+
import cn.jiguang.core.JCoreWireCodec;
|
|
25
|
+
import cn.jiguang.plugins.push.common.JLogger;
|
|
26
|
+
import cn.jpush.android.api.CustomMessage;
|
|
27
|
+
import cn.jpush.android.api.JPushInterface;
|
|
28
|
+
import cn.jpush.android.api.JThirdPlatFormInterface;
|
|
29
|
+
import cn.jpush.android.api.NotificationMessage;
|
|
30
|
+
import cn.jpush.android.local.ActionHelper;
|
|
31
|
+
import cn.jpush.android.service.JNotifyActivity;
|
|
32
|
+
import cn.jpush.android.service.JPushMessageReceiver;
|
|
33
|
+
import com.google.android.gms.common.GoogleApiAvailabilityLight;
|
|
34
|
+
import com.google.android.gms.tasks.TaskCompletionSource;
|
|
35
|
+
import com.google.android.gms.tasks.Tasks;
|
|
36
|
+
import com.google.firebase.FirebaseApp;
|
|
37
|
+
import com.google.firebase.FirebaseOptions;
|
|
38
|
+
import com.google.firebase.messaging.FirebaseMessaging;
|
|
39
|
+
import com.google.firebase.messaging.FirebaseMessagingService;
|
|
40
|
+
import com.google.firebase.messaging.RemoteMessage;
|
|
41
|
+
import java.io.IOException;
|
|
42
|
+
import java.nio.charset.StandardCharsets;
|
|
43
|
+
import java.util.ArrayList;
|
|
44
|
+
import java.util.Collections;
|
|
45
|
+
import java.util.List;
|
|
46
|
+
import java.util.Map;
|
|
47
|
+
import org.junit.After;
|
|
48
|
+
import org.junit.Before;
|
|
49
|
+
import org.junit.Test;
|
|
50
|
+
import org.junit.runner.RunWith;
|
|
51
|
+
import org.mockito.ArgumentCaptor;
|
|
52
|
+
import org.mockito.MockedStatic;
|
|
53
|
+
import org.robolectric.Robolectric;
|
|
54
|
+
import org.robolectric.RobolectricTestRunner;
|
|
55
|
+
import org.robolectric.RuntimeEnvironment;
|
|
56
|
+
import org.robolectric.Shadows;
|
|
57
|
+
import org.robolectric.annotation.Config;
|
|
58
|
+
import org.robolectric.annotation.LooperMode;
|
|
59
|
+
import org.robolectric.util.ReflectionHelpers;
|
|
60
|
+
|
|
61
|
+
@RunWith(RobolectricTestRunner.class)
|
|
62
|
+
@Config(sdk = 28, manifest = Config.NONE)
|
|
63
|
+
@LooperMode(LooperMode.Mode.PAUSED)
|
|
64
|
+
public class FcmAdapterTest {
|
|
65
|
+
private Context context;
|
|
66
|
+
private FcmMessagingService service;
|
|
67
|
+
private NotificationManager notifications;
|
|
68
|
+
private Object firebaseRpc;
|
|
69
|
+
private final List<NotificationMessage> arrived = new ArrayList<>();
|
|
70
|
+
private final List<NotificationMessage> opened = new ArrayList<>();
|
|
71
|
+
private final List<CustomMessage> custom = new ArrayList<>();
|
|
72
|
+
|
|
73
|
+
@Before
|
|
74
|
+
public void setUp() throws Exception {
|
|
75
|
+
context = RuntimeEnvironment.getApplication();
|
|
76
|
+
ReflectionHelpers.setStaticField(JCoreStorage.class, "sAppContext", null);
|
|
77
|
+
ReflectionHelpers.<Map<String, Object>>getStaticField(JCoreStorage.class, "MEMORY_FALLBACK").clear();
|
|
78
|
+
JCoreStorage.setAppContext(context);
|
|
79
|
+
JCoreStorage.setCollectionAuth(context, true);
|
|
80
|
+
JCoreStorage.setPushStopped(context, false);
|
|
81
|
+
ReflectionHelpers.setStaticField(JThirdPlatFormInterface.class, "fcmPlugin", null);
|
|
82
|
+
ReflectionHelpers.setStaticField(JThirdPlatFormInterface.class, "fcmRegistered", false);
|
|
83
|
+
ReflectionHelpers.<java.util.Queue<String>>getStaticField(FirebaseMessagingService.class, "recentlyReceivedMessageIds").clear();
|
|
84
|
+
JLogger.setLoggerEnable(true);
|
|
85
|
+
JLogger.clearRecentLogs();
|
|
86
|
+
notifications = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
87
|
+
notifications.cancelAll();
|
|
88
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
|
|
89
|
+
ActionHelper.getInstance().clearRegisteredReceivers();
|
|
90
|
+
ActionHelper.getInstance().registerReceiver(new JPushMessageReceiver() {
|
|
91
|
+
@Override public void onNotifyMessageArrived(Context c, NotificationMessage message) { arrived.add(message); }
|
|
92
|
+
@Override public void onNotifyMessageOpened(Context c, NotificationMessage message) { opened.add(message); }
|
|
93
|
+
@Override public void onMessage(Context c, CustomMessage message) { custom.add(message); }
|
|
94
|
+
});
|
|
95
|
+
service = Robolectric.buildService(FcmMessagingService.class).create().get();
|
|
96
|
+
// Isolate only the SDK's transport acknowledgement; run its real receive/display code.
|
|
97
|
+
firebaseRpc = mock(Class.forName("com.google.android.gms.cloudmessaging.Rpc"));
|
|
98
|
+
ReflectionHelpers.setField(service, "rpc", firebaseRpc);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@After
|
|
102
|
+
public void tearDown() {
|
|
103
|
+
ActionHelper.getInstance().clearRegisteredReceivers();
|
|
104
|
+
notifications.cancelAll();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Test
|
|
108
|
+
public void coreDiscoversSourceAdapterOnceAndRebindsTheCurrentToken() {
|
|
109
|
+
FirebaseMessaging provider = mock(FirebaseMessaging.class);
|
|
110
|
+
when(provider.getToken()).thenReturn(Tasks.forResult("current_secret_token"));
|
|
111
|
+
GoogleApiAvailabilityLight availability = mock(GoogleApiAvailabilityLight.class);
|
|
112
|
+
when(availability.isGooglePlayServicesAvailable(context)).thenReturn(0);
|
|
113
|
+
ActionHelper dispatcher = mock(ActionHelper.class);
|
|
114
|
+
JCoreTcpEngine engine = synchronousEngine();
|
|
115
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
116
|
+
MockedStatic<FirebaseApp> app = mockStatic(FirebaseApp.class);
|
|
117
|
+
MockedStatic<GoogleApiAvailabilityLight> google = mockStatic(GoogleApiAvailabilityLight.class);
|
|
118
|
+
MockedStatic<ActionHelper> helper = mockStatic(ActionHelper.class);
|
|
119
|
+
MockedStatic<JCoreTcpEngine> tcp = mockStatic(JCoreTcpEngine.class)) {
|
|
120
|
+
firebase.when(FirebaseMessaging::getInstance).thenReturn(provider);
|
|
121
|
+
google.when(GoogleApiAvailabilityLight::getInstance).thenReturn(availability);
|
|
122
|
+
helper.when(ActionHelper::getInstance).thenReturn(dispatcher);
|
|
123
|
+
tcp.when(JCoreTcpEngine::getInstance).thenReturn(engine);
|
|
124
|
+
JThirdPlatFormInterface.initializeFcm(context);
|
|
125
|
+
JThirdPlatFormInterface.initializeFcm(context);
|
|
126
|
+
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
|
127
|
+
app.verify(() -> FirebaseApp.initializeApp(context), times(2));
|
|
128
|
+
verify(provider, times(2)).getToken();
|
|
129
|
+
ArgumentCaptor<Bundle> actions = ArgumentCaptor.forClass(Bundle.class);
|
|
130
|
+
verify(dispatcher, times(2)).doAction(eq(context), eq("third_action"), actions.capture());
|
|
131
|
+
for (Bundle action : actions.getAllValues()) {
|
|
132
|
+
assertEquals("current_secret_token", action.getString("token"));
|
|
133
|
+
assertEquals((byte) 8, action.getByte("platform"));
|
|
134
|
+
}
|
|
135
|
+
assertLogsExclude("current_secret_token");
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@Test
|
|
140
|
+
public void missingFirebaseConfigurationDoesNotEscapeCoreInitialization() {
|
|
141
|
+
GoogleApiAvailabilityLight availability = mock(GoogleApiAvailabilityLight.class);
|
|
142
|
+
when(availability.isGooglePlayServicesAvailable(context)).thenReturn(0);
|
|
143
|
+
JCoreTcpEngine engine = synchronousEngine();
|
|
144
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
145
|
+
MockedStatic<FirebaseApp> app = mockStatic(FirebaseApp.class);
|
|
146
|
+
MockedStatic<GoogleApiAvailabilityLight> google = mockStatic(GoogleApiAvailabilityLight.class);
|
|
147
|
+
MockedStatic<JCoreTcpEngine> tcp = mockStatic(JCoreTcpEngine.class)) {
|
|
148
|
+
firebase.when(FirebaseMessaging::getInstance).thenThrow(new IllegalStateException("private_configuration_details"));
|
|
149
|
+
google.when(GoogleApiAvailabilityLight::getInstance).thenReturn(availability);
|
|
150
|
+
tcp.when(JCoreTcpEngine::getInstance).thenReturn(engine);
|
|
151
|
+
JThirdPlatFormInterface.initializeFcm(context);
|
|
152
|
+
assertTrue(JLogger.getRecentLogs().toString().contains("FCM registration unavailable"));
|
|
153
|
+
assertLogsExclude("private_configuration_details");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@Test
|
|
158
|
+
public void authorizationGrantedAfterSkippedInitRequestsTokenWithoutReconnect() {
|
|
159
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
160
|
+
JCoreStorage.setConnected(context, true);
|
|
161
|
+
FirebaseMessaging provider = mock(FirebaseMessaging.class);
|
|
162
|
+
when(provider.getToken()).thenReturn(Tasks.forResult("consented_secret_token"));
|
|
163
|
+
GoogleApiAvailabilityLight availability = mock(GoogleApiAvailabilityLight.class);
|
|
164
|
+
when(availability.isGooglePlayServicesAvailable(context)).thenReturn(0);
|
|
165
|
+
ActionHelper dispatcher = mock(ActionHelper.class);
|
|
166
|
+
JCoreTcpEngine engine = synchronousEngine();
|
|
167
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
168
|
+
MockedStatic<FirebaseApp> app = mockStatic(FirebaseApp.class);
|
|
169
|
+
MockedStatic<GoogleApiAvailabilityLight> google = mockStatic(GoogleApiAvailabilityLight.class);
|
|
170
|
+
MockedStatic<ActionHelper> helper = mockStatic(ActionHelper.class);
|
|
171
|
+
MockedStatic<JCoreTcpEngine> tcp = mockStatic(JCoreTcpEngine.class);
|
|
172
|
+
MockedStatic<JCoreManager> core = mockStatic(JCoreManager.class)) {
|
|
173
|
+
firebase.when(FirebaseMessaging::getInstance).thenReturn(provider);
|
|
174
|
+
google.when(GoogleApiAvailabilityLight::getInstance).thenReturn(availability);
|
|
175
|
+
helper.when(ActionHelper::getInstance).thenReturn(dispatcher);
|
|
176
|
+
tcp.when(JCoreTcpEngine::getInstance).thenReturn(engine);
|
|
177
|
+
JPushInterface.init(context);
|
|
178
|
+
verifyNoInteractions(provider);
|
|
179
|
+
JCollectionAuth.setAuth(context, true);
|
|
180
|
+
JCollectionAuth.setAuth(context, true);
|
|
181
|
+
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
|
182
|
+
verify(provider).getToken();
|
|
183
|
+
assertEquals("consented_secret_token", tokenAction(dispatcher).getString("token"));
|
|
184
|
+
assertTrue(JCoreStorage.isConnected(context));
|
|
185
|
+
core.verify(() -> JCoreManager.init(context));
|
|
186
|
+
assertLogsExclude("consented_secret_token");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
@Test
|
|
191
|
+
public void grantingAuthorizationWhileStoppedDoesNotRequestRegistration() {
|
|
192
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
193
|
+
JCoreStorage.setPushStopped(context, true);
|
|
194
|
+
try (MockedStatic<JCoreTcpEngine> tcp = mockStatic(JCoreTcpEngine.class)) {
|
|
195
|
+
JCollectionAuth.setAuth(context, true);
|
|
196
|
+
assertTrue(JCollectionAuth.isAuth(context));
|
|
197
|
+
tcp.verifyNoInteractions();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
@Test
|
|
202
|
+
public void revokedAuthorizationCancelsQueuedFcmRegistration() {
|
|
203
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
204
|
+
JCoreTcpEngine engine = mock(JCoreTcpEngine.class);
|
|
205
|
+
try (MockedStatic<JCoreTcpEngine> tcp = mockStatic(JCoreTcpEngine.class);
|
|
206
|
+
MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class)) {
|
|
207
|
+
tcp.when(JCoreTcpEngine::getInstance).thenReturn(engine);
|
|
208
|
+
JCollectionAuth.setAuth(context, true);
|
|
209
|
+
ArgumentCaptor<Runnable> work = ArgumentCaptor.forClass(Runnable.class);
|
|
210
|
+
verify(engine).executeAsync(work.capture());
|
|
211
|
+
JCollectionAuth.setAuth(context, false);
|
|
212
|
+
work.getValue().run();
|
|
213
|
+
firebase.verifyNoInteractions();
|
|
214
|
+
assertFalse(JCollectionAuth.isAuth(context));
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@Test
|
|
219
|
+
public void tokenSuccessDispatchesPlatformEightWithoutPersistingBeforeAck() {
|
|
220
|
+
JCoreStorage.saveThirdToken(context, (byte) 8, "previous_acknowledged_token");
|
|
221
|
+
FirebaseMessaging provider = mock(FirebaseMessaging.class);
|
|
222
|
+
TaskCompletionSource<String> request = new TaskCompletionSource<>();
|
|
223
|
+
when(provider.getToken()).thenReturn(request.getTask());
|
|
224
|
+
ActionHelper dispatcher = mock(ActionHelper.class);
|
|
225
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
226
|
+
MockedStatic<ActionHelper> helper = mockStatic(ActionHelper.class)) {
|
|
227
|
+
firebase.when(FirebaseMessaging::getInstance).thenReturn(provider);
|
|
228
|
+
helper.when(ActionHelper::getInstance).thenReturn(dispatcher);
|
|
229
|
+
assertEquals("previous_acknowledged_token", new FcmPushManager().getToken(context));
|
|
230
|
+
verifyNoInteractions(dispatcher);
|
|
231
|
+
request.setResult("rotated_secret_token");
|
|
232
|
+
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
|
233
|
+
Bundle token = tokenAction(dispatcher);
|
|
234
|
+
assertEquals("rotated_secret_token", token.getString("token"));
|
|
235
|
+
assertEquals((byte) 8, token.getByte("platform"));
|
|
236
|
+
assertEquals("previous_acknowledged_token", JCoreStorage.getThirdToken(context, (byte) 8));
|
|
237
|
+
assertLogsExclude("rotated_secret_token");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@Test
|
|
242
|
+
public void failedTokenRequestDoesNotBindOrLogRawError() {
|
|
243
|
+
FirebaseMessaging provider = mock(FirebaseMessaging.class);
|
|
244
|
+
when(provider.getToken()).thenReturn(Tasks.forException(new IOException("secret_provider_error")));
|
|
245
|
+
ActionHelper dispatcher = mock(ActionHelper.class);
|
|
246
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
247
|
+
MockedStatic<ActionHelper> helper = mockStatic(ActionHelper.class)) {
|
|
248
|
+
firebase.when(FirebaseMessaging::getInstance).thenReturn(provider);
|
|
249
|
+
helper.when(ActionHelper::getInstance).thenReturn(dispatcher);
|
|
250
|
+
new FcmPushManager().getToken(context);
|
|
251
|
+
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
|
252
|
+
verifyNoInteractions(dispatcher);
|
|
253
|
+
assertTrue(JLogger.getRecentLogs().toString().contains("IOException"));
|
|
254
|
+
assertLogsExclude("secret_provider_error");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@Test
|
|
259
|
+
public void tokenCallbackRechecksStopAndAuthorizationAfterRequest() {
|
|
260
|
+
for (boolean stopped : new boolean[]{true, false}) {
|
|
261
|
+
JCoreStorage.setPushStopped(context, false);
|
|
262
|
+
JCoreStorage.setCollectionAuth(context, true);
|
|
263
|
+
FirebaseMessaging provider = mock(FirebaseMessaging.class);
|
|
264
|
+
TaskCompletionSource<String> request = new TaskCompletionSource<>();
|
|
265
|
+
when(provider.getToken()).thenReturn(request.getTask());
|
|
266
|
+
ActionHelper dispatcher = mock(ActionHelper.class);
|
|
267
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
268
|
+
MockedStatic<ActionHelper> helper = mockStatic(ActionHelper.class)) {
|
|
269
|
+
firebase.when(FirebaseMessaging::getInstance).thenReturn(provider);
|
|
270
|
+
helper.when(ActionHelper::getInstance).thenReturn(dispatcher);
|
|
271
|
+
new FcmPushManager().getToken(context);
|
|
272
|
+
JCoreStorage.setPushStopped(context, stopped);
|
|
273
|
+
JCoreStorage.setCollectionAuth(context, stopped);
|
|
274
|
+
request.setResult("late_secret_token");
|
|
275
|
+
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
|
276
|
+
verifyNoInteractions(dispatcher);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
@Test
|
|
282
|
+
public void newTokenInitializesCoreAndForwardsRotation() {
|
|
283
|
+
JCoreStorage.setConnected(context, true);
|
|
284
|
+
FirebaseMessaging provider = mock(FirebaseMessaging.class);
|
|
285
|
+
when(provider.getToken()).thenReturn(Tasks.forResult("new_secret_token"));
|
|
286
|
+
GoogleApiAvailabilityLight availability = mock(GoogleApiAvailabilityLight.class);
|
|
287
|
+
when(availability.isGooglePlayServicesAvailable(context)).thenReturn(0);
|
|
288
|
+
JCoreTcpEngine engine = synchronousEngine();
|
|
289
|
+
try (MockedStatic<JCoreManager> core = mockStatic(JCoreManager.class);
|
|
290
|
+
MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class);
|
|
291
|
+
MockedStatic<FirebaseApp> app = mockStatic(FirebaseApp.class);
|
|
292
|
+
MockedStatic<GoogleApiAvailabilityLight> google = mockStatic(GoogleApiAvailabilityLight.class);
|
|
293
|
+
MockedStatic<JCoreTcpEngine> tcp = mockStatic(JCoreTcpEngine.class)) {
|
|
294
|
+
firebase.when(FirebaseMessaging::getInstance).thenReturn(provider);
|
|
295
|
+
google.when(GoogleApiAvailabilityLight::getInstance).thenReturn(availability);
|
|
296
|
+
tcp.when(JCoreTcpEngine::getInstance).thenReturn(engine);
|
|
297
|
+
service.handleIntent(new Intent("com.google.firebase.messaging.NEW_TOKEN").putExtra("token", "new_secret_token"));
|
|
298
|
+
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
|
299
|
+
core.verify(() -> JCoreManager.init(context));
|
|
300
|
+
ArgumentCaptor<byte[]> body = ArgumentCaptor.forClass(byte[].class);
|
|
301
|
+
verify(engine).enqueueOrSendRequest(eq(context), eq(JCoreWireCodec.CMD_THIRD_TOKEN),
|
|
302
|
+
eq(JCoreWireCodec.VER_THIRD_TOKEN), anyLong(), body.capture(), anyLong(), eq(3),
|
|
303
|
+
any(JCoreTcpEngine.RequestCallback.class));
|
|
304
|
+
assertArrayEquals(JCoreWireCodec.buildThirdTokenPayload("new_secret_token", (byte) 8, false), body.getValue());
|
|
305
|
+
verifyNoInteractions(provider);
|
|
306
|
+
assertLogsExclude("new_secret_token");
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
@Test
|
|
311
|
+
public void stoppedOrUnauthorizedNewTokenDoesNotInitializeCore() {
|
|
312
|
+
try (MockedStatic<JCoreManager> core = mockStatic(JCoreManager.class)) {
|
|
313
|
+
JCoreStorage.setPushStopped(context, true);
|
|
314
|
+
service.onNewToken("ignored");
|
|
315
|
+
JCoreStorage.setPushStopped(context, false);
|
|
316
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
317
|
+
service.onNewToken("ignored");
|
|
318
|
+
core.verifyNoInteractions();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
@Test
|
|
323
|
+
public void emptyTokensAreIgnored() {
|
|
324
|
+
ActionHelper dispatcher = mock(ActionHelper.class);
|
|
325
|
+
try (MockedStatic<ActionHelper> helper = mockStatic(ActionHelper.class)) {
|
|
326
|
+
helper.when(ActionHelper::getInstance).thenReturn(dispatcher);
|
|
327
|
+
FcmPushManager.acceptToken(context, null);
|
|
328
|
+
FcmPushManager.acceptToken(context, "");
|
|
329
|
+
verifyNoInteractions(dispatcher);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
@Test
|
|
334
|
+
public void googlePlayAvailabilityAndNotificationDelegation() {
|
|
335
|
+
GoogleApiAvailabilityLight availability = mock(GoogleApiAvailabilityLight.class);
|
|
336
|
+
when(availability.isGooglePlayServicesAvailable(context)).thenReturn(0, 9);
|
|
337
|
+
try (MockedStatic<GoogleApiAvailabilityLight> google = mockStatic(GoogleApiAvailabilityLight.class);
|
|
338
|
+
MockedStatic<JPushInterface> core = mockStatic(JPushInterface.class)) {
|
|
339
|
+
google.when(GoogleApiAvailabilityLight::getInstance).thenReturn(availability);
|
|
340
|
+
FcmPushManager manager = new FcmPushManager();
|
|
341
|
+
assertTrue(manager.isSupport(context));
|
|
342
|
+
assertFalse(manager.isSupport(context));
|
|
343
|
+
assertFalse(manager.isSupport(null));
|
|
344
|
+
manager.clearNotification(context, 123);
|
|
345
|
+
manager.clearAllNotification(context);
|
|
346
|
+
core.verify(() -> JPushInterface.clearNotificationById(context, 123));
|
|
347
|
+
core.verify(() -> JPushInterface.clearAllNotifications(context));
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
@Test
|
|
352
|
+
public void firebaseInitializationAndApplicationMetadata() {
|
|
353
|
+
FirebaseApp app = mock(FirebaseApp.class);
|
|
354
|
+
FirebaseOptions options = new FirebaseOptions.Builder()
|
|
355
|
+
.setApplicationId("1:123456:android:synthetic").setApiKey("synthetic_api_key").build();
|
|
356
|
+
when(app.getOptions()).thenReturn(options);
|
|
357
|
+
try (MockedStatic<FirebaseApp> firebase = mockStatic(FirebaseApp.class)) {
|
|
358
|
+
firebase.when(FirebaseApp::getInstance).thenReturn(app);
|
|
359
|
+
FcmPushManager manager = new FcmPushManager();
|
|
360
|
+
manager.init(context);
|
|
361
|
+
manager.register(context, new Bundle());
|
|
362
|
+
firebase.verify(() -> FirebaseApp.initializeApp(context), times(2));
|
|
363
|
+
assertEquals(options.getApplicationId(), manager.getAppId(context));
|
|
364
|
+
assertEquals(options.getApiKey(), manager.getAppkey(context));
|
|
365
|
+
assertEquals((byte) 8, manager.getRomType(context));
|
|
366
|
+
assertFalse(manager.isNeedClearToken(context));
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
@Test
|
|
371
|
+
public void firebaseNotificationFieldsFillMetadataAndTapOpensOnce() {
|
|
372
|
+
Bundle payload = metadata("{\"_jmsgid_\":\"fcm_notification\",\"n_extras\":{\"route\":\"synthetic_route\"}}");
|
|
373
|
+
payload.putString("gcm.n.e", "1");
|
|
374
|
+
payload.putString("gcm.n.title", "private_title");
|
|
375
|
+
payload.putString("gcm.n.body", "private_body");
|
|
376
|
+
service.onMessageReceived(new RemoteMessage(payload));
|
|
377
|
+
assertEquals(1, arrived.size());
|
|
378
|
+
assertEquals("private_title", arrived.get(0).notificationTitle);
|
|
379
|
+
assertEquals("private_body", arrived.get(0).notificationContent);
|
|
380
|
+
assertEquals(8, arrived.get(0).platform);
|
|
381
|
+
List<Notification> posted = Shadows.shadowOf(notifications).getAllNotifications();
|
|
382
|
+
assertEquals(1, posted.size());
|
|
383
|
+
assertEquals("private_title", posted.get(0).extras.getString(Notification.EXTRA_TITLE));
|
|
384
|
+
Intent tap = Shadows.shadowOf(posted.get(0).contentIntent).getSavedIntent();
|
|
385
|
+
assertEquals(JNotifyActivity.class.getName(), tap.getComponent().getClassName());
|
|
386
|
+
Robolectric.buildActivity(JNotifyActivity.class, tap).create();
|
|
387
|
+
assertEquals(1, opened.size());
|
|
388
|
+
assertEquals("fcm_notification", opened.get(0).msgId);
|
|
389
|
+
assertTrue(opened.get(0).notificationExtras.contains("synthetic_route"));
|
|
390
|
+
assertLogsExclude("private_title", "private_body", "synthetic_route");
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
@Test
|
|
394
|
+
public void postedDataOnlyTapIsIgnoredAfterStopOrAuthorizationWithdrawal() {
|
|
395
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
396
|
+
ActivityInfo host = new ActivityInfo();
|
|
397
|
+
host.packageName = context.getPackageName();
|
|
398
|
+
host.name = context.getPackageName() + ".MainActivity";
|
|
399
|
+
host.applicationInfo = new ApplicationInfo(context.getApplicationInfo());
|
|
400
|
+
ResolveInfo resolvedHost = new ResolveInfo();
|
|
401
|
+
resolvedHost.activityInfo = host;
|
|
402
|
+
Intent launcher = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER).setPackage(context.getPackageName());
|
|
403
|
+
Shadows.shadowOf(context.getPackageManager()).addResolveInfoForIntent(launcher, resolvedHost);
|
|
404
|
+
for (boolean stopped : new boolean[]{true, false}) {
|
|
405
|
+
JCoreStorage.setPushStopped(context, false);
|
|
406
|
+
JCoreStorage.setCollectionAuth(context, true);
|
|
407
|
+
service.handleIntent(firebaseReceiveIntent("deferred_tap_" + stopped, false));
|
|
408
|
+
List<Notification> posted = Shadows.shadowOf(notifications).getAllNotifications();
|
|
409
|
+
assertEquals(1, posted.size());
|
|
410
|
+
Intent tap = Shadows.shadowOf(posted.get(0).contentIntent).getSavedIntent();
|
|
411
|
+
JCoreStorage.setPushStopped(context, stopped);
|
|
412
|
+
JCoreStorage.setCollectionAuth(context, stopped);
|
|
413
|
+
Robolectric.buildActivity(JNotifyActivity.class, tap).create();
|
|
414
|
+
assertTrue(opened.isEmpty());
|
|
415
|
+
assertNull(Shadows.shadowOf(RuntimeEnvironment.getApplication()).getNextStartedActivity());
|
|
416
|
+
notifications.cancelAll();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
@Test
|
|
421
|
+
public void compressedMetadataRetainsItsOwnTitleAndExtras() {
|
|
422
|
+
Bundle payload = metadata(compress("{\"msg_id\":\"zipped\",\"override_msg_id\":\"\",\"n_title\":\"metadata_title\",\"n_content\":\"metadata_body\",\"n_extras\":{\"route\":\"private_route\"}}"));
|
|
423
|
+
payload.putString("gcm.n.e", "1");
|
|
424
|
+
payload.putString("gcm.n.title", "fallback_title");
|
|
425
|
+
payload.putString("gcm.n.body", "fallback_body");
|
|
426
|
+
service.onMessageReceived(new RemoteMessage(payload));
|
|
427
|
+
assertEquals(1, arrived.size());
|
|
428
|
+
assertEquals("zipped", arrived.get(0).msgId);
|
|
429
|
+
assertEquals("metadata_title", arrived.get(0).notificationTitle);
|
|
430
|
+
assertTrue(arrived.get(0).notificationExtras.contains("private_route"));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
@Test
|
|
434
|
+
public void standardFirebaseDataUsesTransportIdAndPreservesExtras() {
|
|
435
|
+
Bundle payload = new Bundle();
|
|
436
|
+
payload.putString("google.message_id", "transport_id");
|
|
437
|
+
payload.putString("n_title", "Synthetic notification");
|
|
438
|
+
payload.putString("n_content", "Synthetic body");
|
|
439
|
+
payload.putString("route", "synthetic_route");
|
|
440
|
+
service.onMessageReceived(new RemoteMessage(payload));
|
|
441
|
+
assertEquals(1, arrived.size());
|
|
442
|
+
assertEquals("transport_id", arrived.get(0).msgId);
|
|
443
|
+
assertTrue(arrived.get(0).notificationExtras.contains("synthetic_route"));
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
@Test
|
|
447
|
+
public void customDataDoesNotDisplayANotification() {
|
|
448
|
+
service.onMessageReceived(new RemoteMessage(metadata("{\"msg_id\":\"custom_id\",\"message\":\"private_custom_body\",\"content_type\":\"text\",\"extras\":{\"route\":\"private_custom_route\"}}")));
|
|
449
|
+
assertEquals(1, custom.size());
|
|
450
|
+
assertEquals("custom_id", custom.get(0).messageId);
|
|
451
|
+
assertEquals("private_custom_body", custom.get(0).message);
|
|
452
|
+
assertEquals("text", custom.get(0).contentType);
|
|
453
|
+
assertTrue(arrived.isEmpty());
|
|
454
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
455
|
+
assertLogsExclude("private_custom_body", "private_custom_route");
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
@Test
|
|
459
|
+
public void malformedAndOversizedPayloadsDoNotReachCallbacks() {
|
|
460
|
+
service.onMessageReceived(new RemoteMessage(metadata("{broken")));
|
|
461
|
+
service.onMessageReceived(new RemoteMessage(metadata("{\"jg_c\":\"not-gzip\"}")));
|
|
462
|
+
StringBuilder oversized = new StringBuilder();
|
|
463
|
+
for (int i = 0; i < 70000; i++) oversized.append('x');
|
|
464
|
+
service.onMessageReceived(new RemoteMessage(metadata(compress(oversized.toString()))));
|
|
465
|
+
assertTrue(arrived.isEmpty());
|
|
466
|
+
assertTrue(custom.isEmpty());
|
|
467
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
@Test
|
|
471
|
+
public void stoppedAndUnauthorizedNotificationsAreIgnored() {
|
|
472
|
+
String body = "{\"msg_id\":\"blocked\",\"n_content\":\"synthetic\"}";
|
|
473
|
+
JCoreStorage.setPushStopped(context, true);
|
|
474
|
+
service.onMessageReceived(new RemoteMessage(metadata(body)));
|
|
475
|
+
JCoreStorage.setPushStopped(context, false);
|
|
476
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
477
|
+
service.onMessageReceived(new RemoteMessage(metadata(body)));
|
|
478
|
+
JCoreStorage.setCollectionAuth(context, true);
|
|
479
|
+
assertTrue(arrived.isEmpty());
|
|
480
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
@Test
|
|
484
|
+
public void foregroundDisplayDisabledSuppressesNotificationAndArrival() {
|
|
485
|
+
service.onMessageReceived(foregroundSuppressedMessage());
|
|
486
|
+
assertTrue(arrived.isEmpty());
|
|
487
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
@Test
|
|
491
|
+
public void backgroundDataOnlyMessageStillDisplaysAndDispatchesArrival() {
|
|
492
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
493
|
+
RemoteMessage message = foregroundSuppressedMessage();
|
|
494
|
+
assertNull(message.getNotification());
|
|
495
|
+
service.onMessageReceived(message);
|
|
496
|
+
assertEquals(1, arrived.size());
|
|
497
|
+
assertEquals("foreground_suppressed", arrived.get(0).msgId);
|
|
498
|
+
assertEquals(1, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
@Test
|
|
502
|
+
public void foregroundDisplayDecisionUsesCurrentProcessStateForEachMessage() {
|
|
503
|
+
service.onMessageReceived(foregroundSuppressedMessage());
|
|
504
|
+
assertTrue(arrived.isEmpty());
|
|
505
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
506
|
+
service.onMessageReceived(foregroundSuppressedMessage());
|
|
507
|
+
assertEquals(1, arrived.size());
|
|
508
|
+
notifications.cancelAll();
|
|
509
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND);
|
|
510
|
+
service.onMessageReceived(foregroundSuppressedMessage());
|
|
511
|
+
assertEquals(1, arrived.size());
|
|
512
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
@Test
|
|
516
|
+
public void lockedScreenDoesNotSuppressDataOnlyNotification() {
|
|
517
|
+
KeyguardManager keyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
|
|
518
|
+
Shadows.shadowOf(keyguard).setKeyguardLocked(true);
|
|
519
|
+
service.onMessageReceived(foregroundSuppressedMessage());
|
|
520
|
+
assertEquals(1, arrived.size());
|
|
521
|
+
assertEquals(1, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
@Test
|
|
525
|
+
public void stoppedBackgroundCombinedIntentCannotUseFirebaseAutomaticDisplay() {
|
|
526
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
527
|
+
JCoreStorage.setPushStopped(context, true);
|
|
528
|
+
service.handleIntent(firebaseReceiveIntent("stopped_combined", true));
|
|
529
|
+
assertTrue(arrived.isEmpty());
|
|
530
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
531
|
+
verifyNoInteractions(firebaseRpc);
|
|
532
|
+
assertLogsExclude("private_title", "private_body");
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
@Test
|
|
536
|
+
public void unauthorizedBackgroundNotificationIntentCannotUseFirebaseAutomaticDisplay() {
|
|
537
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
538
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
539
|
+
Intent notificationOnly = firebaseReceiveIntent("unauthorized_notification", true);
|
|
540
|
+
notificationOnly.removeExtra("JMessageExtra");
|
|
541
|
+
service.handleIntent(notificationOnly);
|
|
542
|
+
assertTrue(arrived.isEmpty());
|
|
543
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
544
|
+
verifyNoInteractions(firebaseRpc);
|
|
545
|
+
assertLogsExclude("private_title", "private_body");
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
@Test
|
|
549
|
+
public void authorizedBackgroundCombinedIntentKeepsFirebaseDisplayAndDeduplication() {
|
|
550
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
551
|
+
Intent receive = firebaseReceiveIntent("allowed_combined", true);
|
|
552
|
+
service.handleIntent(receive);
|
|
553
|
+
service.handleIntent(new Intent(receive));
|
|
554
|
+
assertEquals(1, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
555
|
+
assertTrue(arrived.isEmpty());
|
|
556
|
+
assertEquals(2, mockingDetails(firebaseRpc).getInvocations().size());
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
@Test
|
|
560
|
+
public void authorizedBackgroundDataOnlyIntentUsesNativeDisplayAndFirebaseDeduplication() {
|
|
561
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
562
|
+
Intent receive = firebaseReceiveIntent("allowed_data", false);
|
|
563
|
+
service.handleIntent(receive);
|
|
564
|
+
service.handleIntent(new Intent(receive));
|
|
565
|
+
assertEquals(1, arrived.size());
|
|
566
|
+
assertEquals("allowed_data", arrived.get(0).msgId);
|
|
567
|
+
assertEquals(1, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
@Test
|
|
571
|
+
public void receiveGateRechecksStateAfterStopWithdrawalAndRegrant() {
|
|
572
|
+
setProcessImportance(ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE);
|
|
573
|
+
JCoreStorage.setPushStopped(context, true);
|
|
574
|
+
service.handleIntent(firebaseReceiveIntent("stopped", true));
|
|
575
|
+
JCoreStorage.setPushStopped(context, false);
|
|
576
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
577
|
+
service.handleIntent(firebaseReceiveIntent("withdrawn", true));
|
|
578
|
+
assertEquals(0, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
579
|
+
JCoreStorage.setCollectionAuth(context, true);
|
|
580
|
+
service.handleIntent(firebaseReceiveIntent("regranted", true));
|
|
581
|
+
assertEquals(1, Shadows.shadowOf(notifications).getAllNotifications().size());
|
|
582
|
+
assertEquals(1, mockingDetails(firebaseRpc).getInvocations().size());
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
@Test
|
|
586
|
+
@Config(sdk = 34)
|
|
587
|
+
public void startupRevokesOldPlayServicesDelegateWithoutTokenOrConsent() {
|
|
588
|
+
JCoreStorage.setPushStopped(context, true);
|
|
589
|
+
JCoreStorage.setCollectionAuth(context, false);
|
|
590
|
+
notifications.setNotificationDelegate("com.google.android.gms");
|
|
591
|
+
try (MockedStatic<FirebaseMessaging> firebase = mockStatic(FirebaseMessaging.class)) {
|
|
592
|
+
Robolectric.buildContentProvider(FcmInitProvider.class).create();
|
|
593
|
+
assertNull(notifications.getNotificationDelegate());
|
|
594
|
+
assertFalse(JCollectionAuth.isAuth(context));
|
|
595
|
+
assertTrue(JCoreStorage.isPushStopped(context));
|
|
596
|
+
firebase.verifyNoInteractions();
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
@Test
|
|
601
|
+
@Config(sdk = 34)
|
|
602
|
+
public void startupPreservesOtherNotificationDelegates() {
|
|
603
|
+
notifications.setNotificationDelegate("other.notification.delegate");
|
|
604
|
+
Robolectric.buildContentProvider(FcmInitProvider.class).create();
|
|
605
|
+
assertEquals("other.notification.delegate", notifications.getNotificationDelegate());
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
@Test
|
|
609
|
+
public void automaticFirebaseTapLaunchesHostAndKeepsCompressedMetadata() {
|
|
610
|
+
ActivityInfo activity = new ActivityInfo();
|
|
611
|
+
activity.packageName = context.getPackageName();
|
|
612
|
+
activity.name = context.getPackageName() + ".MainActivity";
|
|
613
|
+
activity.applicationInfo = new ApplicationInfo(context.getApplicationInfo());
|
|
614
|
+
ResolveInfo resolve = new ResolveInfo();
|
|
615
|
+
resolve.activityInfo = activity;
|
|
616
|
+
Intent launcher = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_LAUNCHER).setPackage(context.getPackageName());
|
|
617
|
+
Shadows.shadowOf(context.getPackageManager()).addResolveInfoForIntent(launcher, resolve);
|
|
618
|
+
Intent tap = new Intent(JPushInterface.ACTION_NOTIFICATION_OPENED)
|
|
619
|
+
.putExtra("JMessageExtra", compress("{\"msg_id\":\"cold_tap\",\"n_extras\":{\"route\":\"synthetic_route\"}}"));
|
|
620
|
+
Robolectric.buildActivity(JNotifyActivity.class, tap).create();
|
|
621
|
+
assertEquals(1, opened.size());
|
|
622
|
+
assertEquals("cold_tap", opened.get(0).msgId);
|
|
623
|
+
Intent launched = Shadows.shadowOf(RuntimeEnvironment.getApplication()).getNextStartedActivity();
|
|
624
|
+
assertNotNull(launched);
|
|
625
|
+
assertEquals(activity.name, launched.getComponent().getClassName());
|
|
626
|
+
assertTrue(opened.get(0).notificationExtras.contains("synthetic_route"));
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
private static Bundle metadata(String json) {
|
|
630
|
+
Bundle payload = new Bundle();
|
|
631
|
+
payload.putString("JMessageExtra", json);
|
|
632
|
+
return payload;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
private static RemoteMessage foregroundSuppressedMessage() {
|
|
636
|
+
return new RemoteMessage(metadata("{\"msg_id\":\"foreground_suppressed\",\"n_content\":\"synthetic\",\"n_foreground\":\"0\"}"));
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
private static Intent firebaseReceiveIntent(String id, boolean notification) {
|
|
640
|
+
Intent receive = new Intent("com.google.android.c2dm.intent.RECEIVE")
|
|
641
|
+
.putExtra("google.message_id", id)
|
|
642
|
+
.putExtras(metadata("{\"msg_id\":\"" + id + "\",\"n_content\":\"private_body\",\"n_foreground\":\"0\"}"));
|
|
643
|
+
if (notification) {
|
|
644
|
+
receive.putExtra("gcm.n.e", "1");
|
|
645
|
+
receive.putExtra("gcm.n.title", "private_title");
|
|
646
|
+
receive.putExtra("gcm.n.body", "private_body");
|
|
647
|
+
receive.putExtra("gcm.n.icon", "android");
|
|
648
|
+
}
|
|
649
|
+
return receive;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
private void setProcessImportance(int importance) {
|
|
653
|
+
ActivityManager.RunningAppProcessInfo process = new ActivityManager.RunningAppProcessInfo();
|
|
654
|
+
process.pid = Process.myPid();
|
|
655
|
+
process.importance = importance;
|
|
656
|
+
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
|
657
|
+
Shadows.shadowOf(manager).setProcesses(Collections.singletonList(process));
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
private static String compress(String json) {
|
|
661
|
+
return "{\"jg_c\":\"" + JCoreCrypto.base64Encode(JCoreCrypto.gzipCompress(json.getBytes(StandardCharsets.UTF_8))) + "\"}";
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
private Bundle tokenAction(ActionHelper dispatcher) {
|
|
665
|
+
ArgumentCaptor<Bundle> action = ArgumentCaptor.forClass(Bundle.class);
|
|
666
|
+
verify(dispatcher).doAction(eq(context), eq("third_action"), action.capture());
|
|
667
|
+
assertEquals(JThirdPlatFormInterface.ACTION_REGISTER_TOKEN, action.getValue().getString("third_key_action"));
|
|
668
|
+
return action.getValue();
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
private static JCoreTcpEngine synchronousEngine() {
|
|
672
|
+
JCoreTcpEngine engine = mock(JCoreTcpEngine.class);
|
|
673
|
+
doAnswer(call -> {
|
|
674
|
+
call.<Runnable>getArgument(0).run();
|
|
675
|
+
return null;
|
|
676
|
+
}).when(engine).executeAsync(any(Runnable.class));
|
|
677
|
+
return engine;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
private static void assertLogsExclude(String... values) {
|
|
681
|
+
String logs = JLogger.getRecentLogs().toString();
|
|
682
|
+
for (String value : values) assertFalse("Sensitive payload appeared in native logger", logs.contains(value));
|
|
683
|
+
}
|
|
684
|
+
}
|