1 // Copyright 2015-present 650 Industries. All rights reserved.
2 package host.exp.exponent
3 
4 import android.util.Log
5 import com.facebook.proguard.annotations.DoNotStrip
6 import com.facebook.react.common.JavascriptException
7 import host.exp.exponent.network.ExponentNetwork
8 import host.exp.expoview.Exponent
9 import okhttp3.CookieJar
10 import okhttp3.OkHttpClient
11 import java.util.concurrent.TimeUnit
12 
13 @DoNotStrip
14 object ReactNativeStaticHelpers {
15   private val TAG = ReactNativeStaticHelpers::class.java.simpleName
16 
17   @DoNotStrip
18   @JvmStatic fun reloadFromManifest(activityId: Int) {
19     try {
20       Class.forName("host.exp.exponent.kernel.Kernel")
21         .getMethod("reloadVisibleExperience", Int::class.javaPrimitiveType)
22         .invoke(null, activityId)
23     } catch (e: Exception) {
24       Log.e("reloadFromManifest", "Unable to reload visible experience", e)
25     }
26   }
27 
28   @DoNotStrip
29   @JvmStatic fun getBundleUrlForActivityId(
30     activityId: Int,
31     mainModuleId: String?,
32     bundleTypeId: String?,
33     host: String?,
34     devMode: Boolean,
35     jsMinify: Boolean
36   ): String? {
37     return try {
38       // TODO(wschurman): the argument order here looks out of order
39       Class.forName("host.exp.exponent.kernel.Kernel")
40         .getMethod(
41           "getBundleUrlForActivityId",
42           Int::class.javaPrimitiveType,
43           String::class.java,
44           String::class.java,
45           String::class.java,
46           Boolean::class.javaPrimitiveType,
47           Boolean::class.javaPrimitiveType
48         )
49         .invoke(null, activityId, mainModuleId, bundleTypeId, host, devMode, jsMinify) as String
50     } catch (e: Exception) {
51       null
52     }
53   }
54 
55   // <= SDK 25
56   @DoNotStrip
57   @JvmStatic fun getBundleUrlForActivityId(
58     activityId: Int,
59     host: String?,
60     jsModulePath: String?,
61     devMode: Boolean,
62     jsMinify: Boolean
63   ): String? {
64     return try {
65       Class.forName("host.exp.exponent.kernel.Kernel")
66         .getMethod(
67           "getBundleUrlForActivityId",
68           Int::class.javaPrimitiveType,
69           String::class.java,
70           String::class.java,
71           Boolean::class.javaPrimitiveType,
72           Boolean::class.javaPrimitiveType
73         )
74         .invoke(null, activityId, host, jsModulePath, devMode, jsMinify) as String
75     } catch (e: Exception) {
76       null
77     }
78   }
79 
80   // <= SDK 21
81   @DoNotStrip
82   @JvmStatic fun getBundleUrlForActivityId(
83     activityId: Int,
84     host: String?,
85     jsModulePath: String?,
86     devMode: Boolean,
87     hmr: Boolean,
88     jsMinify: Boolean
89   ): String? {
90     return try {
91       Class.forName("host.exp.exponent.kernel.Kernel")
92         .getMethod(
93           "getBundleUrlForActivityId",
94           Int::class.javaPrimitiveType,
95           String::class.java,
96           String::class.java,
97           Boolean::class.javaPrimitiveType,
98           Boolean::class.javaPrimitiveType,
99           Boolean::class.javaPrimitiveType
100         )
101         .invoke(null, activityId, host, jsModulePath, devMode, hmr, jsMinify) as String
102     } catch (e: Exception) {
103       null
104     }
105   }
106 
107   @DoNotStrip
108   @JvmStatic fun handleReactNativeError(
109     errorMessage: String?,
110     stackUnversioned: Any?,
111     exceptionId: Int?,
112     isFatal: Boolean?
113   ) {
114     try {
115       Class.forName("host.exp.exponent.kernel.Kernel").getMethod(
116         "handleReactNativeError",
117         String::class.java,
118         Any::class.java,
119         Int::class.java,
120         Boolean::class.java
121       ).invoke(null, errorMessage, stackUnversioned, exceptionId, isFatal)
122     } catch (e: Exception) {
123       throw JavascriptException(errorMessage)
124     }
125   }
126 
127   @DoNotStrip
128   @JvmStatic fun handleReactNativeError(
129     throwable: Throwable?,
130     errorMessage: String?,
131     stackUnversioned: Any?,
132     exceptionId: Int?,
133     isFatal: Boolean?
134   ) {
135     try {
136       Class.forName("host.exp.exponent.kernel.Kernel").getMethod(
137         "handleReactNativeError",
138         Throwable::class.java,
139         String::class.java,
140         Any::class.java,
141         Int::class.java,
142         Boolean::class.java
143       ).invoke(null, throwable, errorMessage, stackUnversioned, exceptionId, isFatal)
144     } catch (e: Exception) {
145       throw JavascriptException(errorMessage)
146     }
147   }
148 
149   @DoNotStrip
150   @JvmStatic fun getBundleSourceForPath(path: String?): String? {
151     return try {
152       Exponent.instance.getBundleSource(path!!)
153     } catch (e: Exception) {
154       null
155     }
156   }
157 
158   private var exponentNetwork: ExponentNetwork? = null
159   fun setExponentNetwork(exponentNetwork: ExponentNetwork?) {
160     this.exponentNetwork = exponentNetwork
161   }
162 
163   @DoNotStrip
164   @JvmStatic fun getOkHttpClient(callingClass: Class<*>): Any {
165     // we build the OkHttp client here so that one cache instance is shared by all concurrent OkHttp instances
166     val version = RNObject.versionForClassname(callingClass.name)
167     val cookieJar =
168       RNObject("com.facebook.react.modules.network.ReactCookieJarContainer").loadVersion(version)
169         .construct().get()
170     val client = OkHttpClient.Builder()
171       .connectTimeout(0, TimeUnit.MILLISECONDS)
172       .readTimeout(0, TimeUnit.MILLISECONDS)
173       .writeTimeout(0, TimeUnit.MILLISECONDS)
174       .cookieJar(cookieJar as CookieJar)
175       .cache(exponentNetwork!!.cache)
176     return client.build()
177   }
178 }
179