1414import android .webkit .MimeTypeMap ;
1515import androidx .annotation .Nullable ;
1616import com .facebook .fbreact .specs .NativeBlobModuleSpec ;
17+ import com .facebook .infer .annotation .Assertions ;
18+ import com .facebook .infer .annotation .Nullsafe ;
1719import com .facebook .proguard .annotations .DoNotStrip ;
1820import com .facebook .react .bridge .Arguments ;
1921import com .facebook .react .bridge .ReactApplicationContext ;
4143import okhttp3 .ResponseBody ;
4244import okio .ByteString ;
4345
46+ @ Nullsafe (Nullsafe .Mode .LOCAL )
4447@ ReactModule (name = NativeBlobModuleSpec .NAME )
4548public class BlobModule extends NativeBlobModuleSpec {
4649
@@ -106,18 +109,21 @@ public boolean supports(ReadableMap data) {
106109 @ Override
107110 public RequestBody toRequestBody (ReadableMap data , String contentType ) {
108111 String type = contentType ;
109- // NULLSAFE_FIXME[Nullable Dereference]
110- if (data .hasKey ("type" ) && !data .getString ("type" ).isEmpty ()) {
112+ if (data .hasKey ("type" )
113+ && data .getString ("type" ) != null
114+ && !data .getString ("type" ).isEmpty ()) {
111115 type = data .getString ("type" );
112116 }
113117 if (type == null ) {
114118 type = "application/octet-stream" ;
115119 }
116120 ReadableMap blob = data .getMap ("blob" );
117- // NULLSAFE_FIXME[Nullable Dereference]
118- String blobId = blob .getString ("blobId" );
119- // NULLSAFE_FIXME[Parameter Not Nullable, Nullable Dereference]
120- byte [] bytes = resolve (blobId , blob .getInt ("offset" ), blob .getInt ("size" ));
121+
122+ // supports() ensures blob is not null, but for nullability we have to check it
123+ Assertions .assertNotNull (blob , "Blob is null even though supports() returned true" );
124+
125+ byte [] bytes =
126+ resolve (blob .getString ("blobId" ), blob .getInt ("offset" ), blob .getInt ("size" ));
121127
122128 return RequestBody .create (MediaType .parse (type ), bytes );
123129 }
@@ -151,8 +157,7 @@ public void initialize() {
151157 }
152158
153159 @ Override
154- // NULLSAFE_FIXME[Inconsistent Subclass Return Annotation]
155- public @ Nullable Map <String , Object > getTypedExportedConstants () {
160+ public Map <String , Object > getTypedExportedConstants () {
156161 // The application can register BlobProvider as a ContentProvider so that blobs are resolvable.
157162 // If it does, it needs to tell us what authority was used via this string resource.
158163 Resources resources = getReactApplicationContext ().getResources ();
@@ -205,11 +210,10 @@ public void remove(String blobId) {
205210 if (sizeParam != null ) {
206211 size = Integer .parseInt (sizeParam , 10 );
207212 }
208- // NULLSAFE_FIXME[Parameter Not Nullable]
209213 return resolve (blobId , offset , size );
210214 }
211215
212- public @ Nullable byte [] resolve (String blobId , int offset , int size ) {
216+ public @ Nullable byte [] resolve (@ Nullable String blobId , int offset , int size ) {
213217 synchronized (mBlobs ) {
214218 byte [] data = mBlobs .get (blobId );
215219 if (data == null ) {
@@ -226,7 +230,6 @@ public void remove(String blobId) {
226230 }
227231
228232 public @ Nullable byte [] resolve (ReadableMap blob ) {
229- // NULLSAFE_FIXME[Parameter Not Nullable]
230233 return resolve (blob .getString ("blobId" ), blob .getInt ("offset" ), blob .getInt ("size" ));
231234 }
232235
@@ -273,9 +276,8 @@ private byte[] getBytesFromUri(Uri contentUri) throws IOException {
273276 }
274277 }
275278
276- private String getNameFromUri (Uri contentUri ) {
279+ private @ Nullable String getNameFromUri (Uri contentUri ) {
277280 if ("file" .equals (contentUri .getScheme ())) {
278- // NULLSAFE_FIXME[Return Not Nullable]
279281 return contentUri .getLastPathSegment ();
280282 }
281283 String [] projection = {MediaStore .MediaColumns .DISPLAY_NAME };
@@ -286,14 +288,12 @@ private String getNameFromUri(Uri contentUri) {
286288 if (metaCursor != null ) {
287289 try {
288290 if (metaCursor .moveToFirst ()) {
289- // NULLSAFE_FIXME[Return Not Nullable]
290291 return metaCursor .getString (0 );
291292 }
292293 } finally {
293294 metaCursor .close ();
294295 }
295296 }
296- // NULLSAFE_FIXME[Return Not Nullable]
297297 return contentUri .getLastPathSegment ();
298298 }
299299
@@ -321,15 +321,13 @@ private String getMimeTypeFromUri(Uri contentUri) {
321321 return type ;
322322 }
323323
324- private WebSocketModule getWebSocketModule (String reason ) {
324+ private @ Nullable WebSocketModule getWebSocketModule (String reason ) {
325325 ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn ();
326326
327327 if (reactApplicationContext != null ) {
328- // NULLSAFE_FIXME[Return Not Nullable]
329328 return reactApplicationContext .getNativeModule (WebSocketModule .class );
330329 }
331330
332- // NULLSAFE_FIXME[Return Not Nullable]
333331 return null ;
334332 }
335333
@@ -340,11 +338,9 @@ public void addNetworkingHandler() {
340338 if (reactApplicationContext != null ) {
341339 NetworkingModule networkingModule =
342340 reactApplicationContext .getNativeModule (NetworkingModule .class );
343- // NULLSAFE_FIXME[Nullable Dereference]
341+ Assertions . assertNotNull ( networkingModule , "NetworkingModule is null" );
344342 networkingModule .addUriHandler (mNetworkingUriHandler );
345- // NULLSAFE_FIXME[Nullable Dereference]
346343 networkingModule .addRequestBodyHandler (mNetworkingRequestBodyHandler );
347- // NULLSAFE_FIXME[Nullable Dereference]
348344 networkingModule .addResponseHandler (mNetworkingResponseHandler );
349345 }
350346 }
@@ -378,14 +374,10 @@ public void sendOverSocket(ReadableMap blob, double idDouble) {
378374 WebSocketModule webSocketModule = getWebSocketModule ("sendOverSocket" );
379375
380376 if (webSocketModule != null ) {
381- // NULLSAFE_FIXME[Parameter Not Nullable]
382377 byte [] data = resolve (blob .getString ("blobId" ), blob .getInt ("offset" ), blob .getInt ("size" ));
383378
384379 if (data != null ) {
385380 webSocketModule .sendBinary (ByteString .of (data ), id );
386- } else {
387- // NULLSAFE_FIXME[Parameter Not Nullable]
388- webSocketModule .sendBinary ((ByteString ) null , id );
389381 }
390382 }
391383 }
@@ -396,24 +388,24 @@ public void createFromParts(ReadableArray parts, String blobId) {
396388 ArrayList <byte []> partList = new ArrayList <>(parts .size ());
397389 for (int i = 0 ; i < parts .size (); i ++) {
398390 ReadableMap part = parts .getMap (i );
399- // NULLSAFE_FIXME[Nullable Dereference]
400- switch (part .getString ("type" )) {
391+ Assertions .assertNotNull (part , "Blob part is null" );
392+ String type = part .getString ("type" );
393+ Assertions .assertNotNull (type , "Invalid type for blob: null" );
394+ switch (type ) {
401395 case "blob" :
402- // NULLSAFE_FIXME[Nullable Dereference]
403396 ReadableMap blob = part .getMap ("data" );
404- // NULLSAFE_FIXME[Nullable Dereference]
397+ Assertions . assertNotNull ( blob , "Blob is null" );
405398 totalBlobSize += blob .getInt ("size" );
406- // NULLSAFE_FIXME[Parameter Not Nullable]
407399 partList .add (i , resolve (blob ));
408400 break ;
409401 case "string" :
410- // NULLSAFE_FIXME[Nullable Dereference]
411- byte [] bytes = part .getString ("data" ).getBytes (Charset .forName ("UTF-8" ));
402+ String data = part .getString ("data" );
403+ Assertions .assertNotNull (data , "Data is null" );
404+ byte [] bytes = data .getBytes (Charset .forName ("UTF-8" ));
412405 totalBlobSize += bytes .length ;
413406 partList .add (i , bytes );
414407 break ;
415408 default :
416- // NULLSAFE_FIXME[Nullable Dereference]
417409 throw new IllegalArgumentException ("Invalid type for blob: " + part .getString ("type" ));
418410 }
419411 }
0 commit comments