Skip to content

Commit 9b30cdd

Browse files
GijsWeteringsfacebook-github-bot
authored andcommitted
fix nullsafe FIXMEs for NetworkingModule.java and mark nullsafe
Summary: Gone trough all the FIXMEs added in the previous diff by the nullsafe tool, marked the class as nullsafe and ensured no remaining violations. Changelog: [Android][Fixed] Made NetworkingModule.java nullsafe Reviewed By: cortinico Differential Revision: D71979590 fbshipit-source-id: 0ddf764f4707d2ee76ab99bc1a09a4e2a7e6b794
1 parent 70b4265 commit 9b30cdd

File tree

2 files changed

+77
-40
lines changed

2 files changed

+77
-40
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public boolean supports(ReadableMap data) {
107107
}
108108

109109
@Override
110-
public RequestBody toRequestBody(ReadableMap data, String contentType) {
110+
public RequestBody toRequestBody(ReadableMap data, @Nullable String contentType) {
111111
String type = contentType;
112112
if (data.hasKey("type")
113113
&& data.getString("type") != null

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java

+76-39
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
import androidx.annotation.Nullable;
1414
import com.facebook.common.logging.FLog;
1515
import com.facebook.fbreact.specs.NativeNetworkingAndroidSpec;
16+
import com.facebook.infer.annotation.Assertions;
17+
import com.facebook.infer.annotation.Nullsafe;
1618
import com.facebook.react.bridge.Arguments;
1719
import com.facebook.react.bridge.ReactApplicationContext;
1820
import com.facebook.react.bridge.ReactMethod;
@@ -48,6 +50,7 @@
4850
import okio.Okio;
4951

5052
/** Implements the XMLHttpRequest JavaScript interface. */
53+
@Nullsafe(Nullsafe.Mode.LOCAL)
5154
@ReactModule(name = NativeNetworkingAndroidSpec.NAME)
5255
public final class NetworkingModule extends NativeNetworkingAndroidSpec {
5356

@@ -69,7 +72,7 @@ public interface RequestBodyHandler {
6972
boolean supports(ReadableMap map);
7073

7174
/** Returns the {@link RequestBody} for the JS body payload. */
72-
RequestBody toRequestBody(ReadableMap map, String contentType);
75+
RequestBody toRequestBody(ReadableMap map, @Nullable String contentType);
7376
}
7477

7578
/** Allows adding custom handling to build the JS body payload from the {@link ResponseBody}. */
@@ -238,7 +241,7 @@ public void sendRequest(
238241
String url,
239242
double requestIdAsDouble,
240243
ReadableArray headers,
241-
ReadableMap data,
244+
@Nullable ReadableMap data,
242245
String responseType,
243246
boolean useIncrementalUpdates,
244247
double timeoutAsDouble,
@@ -272,7 +275,7 @@ public void sendRequestInternal(
272275
String url,
273276
final int requestId,
274277
ReadableArray headers,
275-
ReadableMap data,
278+
@Nullable ReadableMap data,
276279
final String responseType,
277280
final boolean useIncrementalUpdates,
278281
int timeout,
@@ -322,10 +325,11 @@ public void sendRequestInternal(
322325
clientBuilder.addNetworkInterceptor(
323326
chain -> {
324327
Response originalResponse = chain.proceed(chain.request());
328+
ResponseBody originalResponseBody = originalResponse.body();
329+
Assertions.assertNotNull(originalResponseBody);
325330
ProgressResponseBody responseBody =
326331
new ProgressResponseBody(
327-
// NULLSAFE_FIXME[Parameter Not Nullable]
328-
originalResponse.body(),
332+
originalResponseBody,
329333
new ProgressListener() {
330334
long last = System.nanoTime();
331335

@@ -386,7 +390,6 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
386390
|| method.toLowerCase(Locale.ROOT).equals("head")) {
387391
requestBody = RequestBodyUtil.getEmptyBody(method);
388392
} else if (handler != null) {
389-
// NULLSAFE_FIXME[Parameter Not Nullable]
390393
requestBody = handler.toRequestBody(data, contentType);
391394
} else if (data.hasKey(REQUEST_BODY_KEY_STRING)) {
392395
if (contentType == null) {
@@ -400,8 +403,10 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
400403
String body = data.getString(REQUEST_BODY_KEY_STRING);
401404
MediaType contentMediaType = MediaType.parse(contentType);
402405
if (RequestBodyUtil.isGzipEncoding(contentEncoding)) {
403-
// NULLSAFE_FIXME[Parameter Not Nullable]
404-
requestBody = RequestBodyUtil.createGzip(contentMediaType, body);
406+
requestBody = null;
407+
if (contentMediaType != null && body != null) {
408+
requestBody = RequestBodyUtil.createGzip(contentMediaType, body);
409+
}
405410
if (requestBody == null) {
406411
ResponseUtil.onRequestError(
407412
reactApplicationContext, requestId, "Failed to gzip request body", null);
@@ -415,7 +420,12 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
415420
contentMediaType == null
416421
? StandardCharsets.UTF_8
417422
: contentMediaType.charset(StandardCharsets.UTF_8);
418-
// NULLSAFE_FIXME[Parameter Not Nullable, Nullable Dereference]
423+
Assertions.assertNotNull(charset);
424+
if (body == null) {
425+
ResponseUtil.onRequestError(
426+
reactApplicationContext, requestId, "Received request but body was empty", null);
427+
return;
428+
}
419429
requestBody = RequestBody.create(contentMediaType, body.getBytes(charset));
420430
}
421431
} else if (data.hasKey(REQUEST_BODY_KEY_BASE64)) {
@@ -428,9 +438,24 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
428438
return;
429439
}
430440
String base64String = data.getString(REQUEST_BODY_KEY_BASE64);
441+
Assertions.assertNotNull(base64String);
442+
431443
MediaType contentMediaType = MediaType.parse(contentType);
432-
// NULLSAFE_FIXME[Parameter Not Nullable]
433-
requestBody = RequestBody.create(contentMediaType, ByteString.decodeBase64(base64String));
444+
if (contentMediaType == null) {
445+
ResponseUtil.onRequestError(
446+
reactApplicationContext,
447+
requestId,
448+
"Invalid content type specified: " + contentType,
449+
null);
450+
return;
451+
}
452+
ByteString base64DecodedString = ByteString.decodeBase64(base64String);
453+
if (base64DecodedString == null) {
454+
ResponseUtil.onRequestError(
455+
reactApplicationContext, requestId, "Request body base64 string was invalid", null);
456+
return;
457+
}
458+
requestBody = RequestBody.create(contentMediaType, base64DecodedString);
434459
} else if (data.hasKey(REQUEST_BODY_KEY_URI)) {
435460
if (contentType == null) {
436461
ResponseUtil.onRequestError(
@@ -441,8 +466,12 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
441466
return;
442467
}
443468
String uri = data.getString(REQUEST_BODY_KEY_URI);
469+
if (uri == null) {
470+
ResponseUtil.onRequestError(
471+
reactApplicationContext, requestId, "Request body URI field was set but null", null);
472+
return;
473+
}
444474
InputStream fileInputStream =
445-
// NULLSAFE_FIXME[Parameter Not Nullable]
446475
RequestBodyUtil.getFileInputStream(getReactApplicationContext(), uri);
447476
if (fileInputStream == null) {
448477
ResponseUtil.onRequestError(
@@ -455,8 +484,12 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
455484
contentType = "multipart/form-data";
456485
}
457486
ReadableArray parts = data.getArray(REQUEST_BODY_KEY_FORMDATA);
487+
if (parts == null) {
488+
ResponseUtil.onRequestError(
489+
reactApplicationContext, requestId, "Received request but form data was empty", null);
490+
return;
491+
}
458492
MultipartBody.Builder multipartBuilder =
459-
// NULLSAFE_FIXME[Parameter Not Nullable]
460493
constructMultipartBody(parts, contentType, requestId);
461494
if (multipartBuilder == null) {
462495
return;
@@ -467,7 +500,6 @@ public void onProgress(long bytesWritten, long contentLength, boolean done) {
467500
requestBody = RequestBodyUtil.getEmptyBody(method);
468501
}
469502

470-
// NULLSAFE_FIXME[Parameter Not Nullable]
471503
requestBuilder.method(method, wrapRequestBodyWithProgressEmitter(requestBody, requestId));
472504

473505
addRequest(requestId);
@@ -518,8 +550,12 @@ public void onResponse(Call call, Response response) throws IOException {
518550
// See
519551
// https://github.com/square/okhttp/blob/5b37cda9e00626f43acf354df145fd452c3031f1/okhttp/src/main/java/okhttp3/internal/http/BridgeInterceptor.java#L76-L111
520552
ResponseBody responseBody = response.body();
521-
if ("gzip".equalsIgnoreCase(response.header("Content-Encoding"))
522-
&& responseBody != null) {
553+
if (responseBody == null) {
554+
ResponseUtil.onRequestError(
555+
reactApplicationContext, requestId, "Response body is null", null);
556+
return;
557+
}
558+
if ("gzip".equalsIgnoreCase(response.header("Content-Encoding"))) {
523559
GzipSource gzipSource = new GzipSource(responseBody.source());
524560
String contentType = response.header("Content-Type");
525561
responseBody =
@@ -532,7 +568,6 @@ public void onResponse(Call call, Response response) throws IOException {
532568
// Check if a handler is registered
533569
for (ResponseHandler handler : mResponseHandlers) {
534570
if (handler.supports(responseType)) {
535-
// NULLSAFE_FIXME[Parameter Not Nullable]
536571
WritableMap res = handler.toResponseData(responseBody);
537572
ResponseUtil.onDataReceived(reactApplicationContext, requestId, res);
538573
ResponseUtil.onRequestSuccess(reactApplicationContext, requestId);
@@ -544,7 +579,6 @@ public void onResponse(Call call, Response response) throws IOException {
544579
// response,
545580
// periodically send response data updates to JS.
546581
if (useIncrementalUpdates && responseType.equals("text")) {
547-
// NULLSAFE_FIXME[Parameter Not Nullable]
548582
readWithProgress(requestId, responseBody);
549583
ResponseUtil.onRequestSuccess(reactApplicationContext, requestId);
550584
return;
@@ -554,7 +588,6 @@ public void onResponse(Call call, Response response) throws IOException {
554588
String responseString = "";
555589
if (responseType.equals("text")) {
556590
try {
557-
// NULLSAFE_FIXME[Nullable Dereference]
558591
responseString = responseBody.string();
559592
} catch (IOException e) {
560593
if (response.request().method().equalsIgnoreCase("HEAD")) {
@@ -569,7 +602,6 @@ public void onResponse(Call call, Response response) throws IOException {
569602
}
570603
}
571604
} else if (responseType.equals("base64")) {
572-
// NULLSAFE_FIXME[Nullable Dereference]
573605
responseString = Base64.encodeToString(responseBody.bytes(), Base64.NO_WRAP);
574606
}
575607
ResponseUtil.onDataReceived(reactApplicationContext, requestId, responseString);
@@ -582,10 +614,9 @@ public void onResponse(Call call, Response response) throws IOException {
582614
});
583615
}
584616

585-
private RequestBody wrapRequestBodyWithProgressEmitter(
586-
final RequestBody requestBody, final int requestId) {
617+
private @Nullable RequestBody wrapRequestBodyWithProgressEmitter(
618+
@Nullable final RequestBody requestBody, final int requestId) {
587619
if (requestBody == null) {
588-
// NULLSAFE_FIXME[Return Not Nullable]
589620
return null;
590621
}
591622
final ReactApplicationContext reactApplicationContext =
@@ -622,8 +653,9 @@ private void readWithProgress(int requestId, ResponseBody responseBody) throws I
622653
responseBody.contentType() == null
623654
? StandardCharsets.UTF_8
624655
: responseBody.contentType().charset(StandardCharsets.UTF_8);
656+
Assertions.assertNotNull(
657+
charset, "Null character set for Content-Type: " + responseBody.contentType());
625658

626-
// NULLSAFE_FIXME[Parameter Not Nullable]
627659
ProgressiveStringDecoder streamDecoder = new ProgressiveStringDecoder(charset);
628660
InputStream inputStream = responseBody.byteStream();
629661
try {
@@ -702,18 +734,25 @@ public void removeListeners(double count) {}
702734

703735
private @Nullable MultipartBody.Builder constructMultipartBody(
704736
ReadableArray body, String contentType, int requestId) {
705-
MultipartBody.Builder multipartBuilder = new MultipartBody.Builder();
706-
// NULLSAFE_FIXME[Parameter Not Nullable]
707-
multipartBuilder.setType(MediaType.parse(contentType));
708-
709737
final ReactApplicationContext reactApplicationContext =
710738
getReactApplicationContextIfActiveOrWarn();
739+
MultipartBody.Builder multipartBuilder = new MultipartBody.Builder();
740+
MediaType mediaType = MediaType.parse(contentType);
741+
if (mediaType == null) {
742+
ResponseUtil.onRequestError(reactApplicationContext, requestId, "Invalid media type.", null);
743+
return null;
744+
}
745+
multipartBuilder.setType(mediaType);
711746

712747
for (int i = 0, size = body.size(); i < size; i++) {
713748
ReadableMap bodyPart = body.getMap(i);
749+
if (bodyPart == null) {
750+
ResponseUtil.onRequestError(
751+
reactApplicationContext, requestId, "Unrecognized FormData part.", null);
752+
return null;
753+
}
714754

715755
// Determine part's content type.
716-
// NULLSAFE_FIXME[Nullable Dereference]
717756
ReadableArray headersArray = bodyPart.getArray("headers");
718757
Headers headers = extractHeaders(headersArray, null);
719758
if (headers == null) {
@@ -733,14 +772,12 @@ public void removeListeners(double count) {}
733772
headers = headers.newBuilder().removeAll(CONTENT_TYPE_HEADER_NAME).build();
734773
}
735774

736-
// NULLSAFE_FIXME[Nullable Dereference]
737-
if (bodyPart.hasKey(REQUEST_BODY_KEY_STRING)) {
738-
// NULLSAFE_FIXME[Nullable Dereference]
775+
if (bodyPart.hasKey(REQUEST_BODY_KEY_STRING)
776+
&& bodyPart.getString(REQUEST_BODY_KEY_STRING) != null) {
739777
String bodyValue = bodyPart.getString(REQUEST_BODY_KEY_STRING);
740-
// NULLSAFE_FIXME[Parameter Not Nullable]
741778
multipartBuilder.addPart(headers, RequestBody.create(partContentType, bodyValue));
742-
// NULLSAFE_FIXME[Nullable Dereference]
743-
} else if (bodyPart.hasKey(REQUEST_BODY_KEY_URI)) {
779+
} else if (bodyPart.hasKey(REQUEST_BODY_KEY_URI)
780+
&& bodyPart.getString(REQUEST_BODY_KEY_URI) != null) {
744781
if (partContentType == null) {
745782
ResponseUtil.onRequestError(
746783
reactApplicationContext,
@@ -749,10 +786,8 @@ public void removeListeners(double count) {}
749786
null);
750787
return null;
751788
}
752-
// NULLSAFE_FIXME[Nullable Dereference]
753789
String fileContentUriStr = bodyPart.getString(REQUEST_BODY_KEY_URI);
754790
InputStream fileInputStream =
755-
// NULLSAFE_FIXME[Parameter Not Nullable]
756791
RequestBodyUtil.getFileInputStream(getReactApplicationContext(), fileContentUriStr);
757792
if (fileInputStream == null) {
758793
ResponseUtil.onRequestError(
@@ -785,8 +820,10 @@ public void removeListeners(double count) {}
785820
if (header == null || header.size() != 2) {
786821
return null;
787822
}
788-
// NULLSAFE_FIXME[Parameter Not Nullable]
789-
String headerName = HeaderUtil.stripHeaderName(header.getString(0));
823+
String headerName = null;
824+
if (header.getString(0) != null) {
825+
headerName = HeaderUtil.stripHeaderName(header.getString(0));
826+
}
790827
String headerValue = header.getString(1);
791828
if (headerName == null || headerValue == null) {
792829
return null;

0 commit comments

Comments
 (0)