Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java #50067

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
d967c8e
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
2715cf7
Fix Nullsafe FIXMEs for StackTraceHelper.java and mark Nullsafe
GijsWeterings Mar 17, 2025
6d490e9
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
65bf383
Fix Nullsafe FIXMEs for MultipartStreamReader.java
GijsWeterings Mar 17, 2025
526e0ba
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
f78c1d3
Fix Nullsafe FIXMEs for JSDebuggerWebSocketClient.java and mark nullsafe
GijsWeterings Mar 17, 2025
7e46cf0
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
b0d6cad
Fix Nullsafe FIXMEs for DevServerHelper.java and mark nullsafe
GijsWeterings Mar 17, 2025
8d61941
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
8c35ef4
Fix Nullsafe FIXMEs for CxxInspectorPackagerConnection.java and mark …
GijsWeterings Mar 17, 2025
bb45cd2
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
94fddf5
Fix Nullsafe FIXMEs for DebugOverlayController.java and mark nullsafe
GijsWeterings Mar 17, 2025
5f75f1c
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
544e9d6
Fix Nullsafe FIXMES for BundleDownloader.java
GijsWeterings Mar 17, 2025
308c2e9
Apply Nullsafe FIXMEs for xplat/js/react-native-github/packages/react…
GijsWeterings Mar 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.common.DebugServerException;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
Expand All @@ -32,6 +33,7 @@
import org.json.JSONException;
import org.json.JSONObject;

@Nullsafe(Nullsafe.Mode.LOCAL)
public class BundleDownloader {
private static final String TAG = "BundleDownloader";

Expand Down Expand Up @@ -140,22 +142,29 @@ public void onResponse(Call call, final Response response) throws IOException {
final String url = response.request().url().toString();
// Make sure the result is a multipart response and parse the boundary.
String contentType = response.header("content-type");
if (contentType == null) {
// fallback to empty string for nullability
contentType = "";
}
Pattern regex = Pattern.compile("multipart/mixed;.*boundary=\"([^\"]+)\"");
Matcher match = regex.matcher(contentType);
if (match.find()) {
processMultipartResponse(url, r, match.group(1), outputFile, bundleInfo, callback);
if (!contentType.isEmpty() && match.find()) {
String boundary = Assertions.assertNotNull(match.group(1));
processMultipartResponse(url, r, boundary, outputFile, bundleInfo, callback);
} else {
// In case the server doesn't support multipart/mixed responses, fallback to normal
// download.
try (ResponseBody body = r.body()) {
processBundleResult(
url,
r.code(),
r.headers(),
r.body().source(),
outputFile,
bundleInfo,
callback);
if (body != null) {
processBundleResult(
url,
r.code(),
r.headers(),
body.source(),
outputFile,
bundleInfo,
callback);
}
}
}
}
Expand All @@ -171,7 +180,17 @@ private void processMultipartResponse(
@Nullable final BundleInfo bundleInfo,
final DevBundleDownloadListener callback)
throws IOException {

if (response.body() == null) {
callback.onFailure(
new DebugServerException(
"Error while reading multipart response.\n\nResponse body was empty: "
+ response.code()
+ "\n\n"
+ "URL: "
+ url.toString()
+ "\n\n"));
return;
}
MultipartStreamReader bodyReader =
new MultipartStreamReader(response.body().source(), boundary);
boolean completed =
Expand Down Expand Up @@ -243,7 +262,7 @@ private void processBundleResult(
Headers headers,
BufferedSource body,
File outputFile,
BundleInfo bundleInfo,
@Nullable BundleInfo bundleInfo,
DevBundleDownloadListener callback)
throws IOException {
// Check for server errors. If the server error has the expected form, fail with more info.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import java.io.Closeable;
Expand All @@ -21,7 +22,8 @@
import okhttp3.WebSocketListener;

/** Java wrapper around a C++ InspectorPackagerConnection. */
/* package */ class CxxInspectorPackagerConnection implements IInspectorPackagerConnection {
/* package */ @Nullsafe(Nullsafe.Mode.LOCAL)
class CxxInspectorPackagerConnection implements IInspectorPackagerConnection {
static {
DevSupportSoLoader.staticInit();
}
Expand All @@ -39,7 +41,7 @@ private static native HybridData initHybrid(

public native void closeQuietly();

public native void sendEventToAllConnections(String event);
public native void sendEventToAllConnections(@Nullable String event);

/** Java wrapper around a C++ IWebSocketDelegate, allowing us to call the interface from Java. */
@DoNotStrip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.UiThreadUtil;
import com.facebook.react.common.ReactConstants;
Expand All @@ -26,7 +27,8 @@
* Helper class for controlling overlay view with FPS and JS FPS info that gets added directly
* to @{link WindowManager} instance.
*/
/* package */ class DebugOverlayController {
/* package */ @Nullsafe(Nullsafe.Mode.LOCAL)
class DebugOverlayController {

public static void requestPermission(Context context) {
// Get permission to show debug overlay in dev builds.
Expand Down Expand Up @@ -57,6 +59,7 @@ private static boolean hasPermission(Context context, String permission) {
PackageInfo info =
context
.getPackageManager()
// NULLSAFE_FIXME[Nullable Dereference]
.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
if (info.requestedPermissions != null) {
for (String p : info.requestedPermissions) {
Expand All @@ -73,7 +76,7 @@ private static boolean hasPermission(Context context, String permission) {

private static boolean canHandleIntent(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
return intent.resolveActivity(packageManager) != null;
return packageManager != null && intent.resolveActivity(packageManager) != null;
}

private final WindowManager mWindowManager;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.devsupport.interfaces.DevBundleDownloadListener;
Expand Down Expand Up @@ -59,6 +60,7 @@
* <li>Genymotion emulator with default settings: 10.0.3.2
* </ul>
*/
@Nullsafe(Nullsafe.Mode.LOCAL)
public class DevServerHelper {
private static final int HTTP_CONNECT_TIMEOUT_MS = 5000;

Expand Down Expand Up @@ -205,10 +207,13 @@ public void openInspectorConnection() {
protected Void doInBackground(Void... params) {
Map<String, String> metadata =
AndroidInfoHelpers.getInspectorHostMetadata(mApplicationContext);

String deviceName = metadata.get("deviceName");
if (deviceName == null) {
FLog.w(ReactConstants.TAG, "Could not get device name from Inspector Host Metadata.");
return null;
}
mInspectorPackagerConnection =
new CxxInspectorPackagerConnection(
getInspectorDeviceUrl(), metadata.get("deviceName"), mPackageName);
new CxxInspectorPackagerConnection(getInspectorDeviceUrl(), deviceName, mPackageName);
mInspectorPackagerConnection.connect();
return null;
}
Expand Down Expand Up @@ -447,7 +452,7 @@ public String getSourceUrl(String mainModuleName) {
final Request request = new Request.Builder().url(resourceURL).build();

try (Response response = mClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
if (!response.isSuccessful() || response.body() == null) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,13 +223,15 @@ private void logJSException(Exception e) {
if (e instanceof JavascriptException) {
FLog.e(ReactConstants.TAG, "Exception in native call from JS", e);
showNewError(
// NULLSAFE_FIXME[Nullable Dereference]
e.getMessage().toString(), new StackFrame[] {}, JSEXCEPTION_ERROR_COOKIE, ErrorType.JS);
} else {
showNewJavaError(message.toString(), e);
}
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void showNewJavaError(@Nullable String message, Throwable e) {
FLog.e(ReactConstants.TAG, "Exception in native call", e);
showNewError(
Expand All @@ -242,16 +244,19 @@ public void showNewJavaError(@Nullable String message, Throwable e) {
* called.
*/
@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void addCustomDevOption(String optionName, DevOptionHandler optionHandler) {
mCustomDevOptions.put(optionName, optionHandler);
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void showNewJSError(String message, ReadableArray details, int errorCookie) {
showNewError(message, StackTraceHelper.convertJsStackTrace(details), errorCookie, ErrorType.JS);
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void registerErrorCustomizer(ErrorCustomizer errorCustomizer) {
if (mErrorCustomizers == null) {
mErrorCustomizers = new ArrayList<>();
Expand All @@ -260,6 +265,7 @@ public void registerErrorCustomizer(ErrorCustomizer errorCustomizer) {
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public Pair<String, StackFrame[]> processErrorCustomizers(Pair<String, StackFrame[]> errorInfo) {
if (mErrorCustomizers != null) {
for (ErrorCustomizer errorCustomizer : mErrorCustomizers) {
Expand All @@ -281,10 +287,12 @@ public void hideRedboxDialog() {
mRedBoxSurfaceDelegate.hide();
}

// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public @Nullable View createRootView(String appKey) {
return mReactInstanceDevHelper.createRootView(appKey);
}

// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void destroyRootView(View rootView) {
mReactInstanceDevHelper.destroyRootView(rootView);
}
Expand Down Expand Up @@ -518,12 +526,14 @@ public View getView(int position, @Nullable View convertView, ViewGroup parent)
mDevOptionsDialog =
new AlertDialog.Builder(context)
.setCustomTitle(header)
// NULLSAFE_FIXME[Not Vetted Third-Party]
.setAdapter(
adapter,
(dialog, which) -> {
optionHandlers[which].onOptionSelected();
mDevOptionsDialog = null;
})
// NULLSAFE_FIXME[Not Vetted Third-Party]
.setOnCancelListener(dialog -> mDevOptionsDialog = null)
.create();
mDevOptionsDialog.show();
Expand All @@ -538,6 +548,7 @@ private String getJSExecutorDescription() {
try {
return getReactInstanceDevHelper().getJavaScriptExecutorFactory().toString();
} catch (IllegalStateException e) {
// NULLSAFE_FIXME[Return Not Nullable]
return null;
}
}
Expand Down Expand Up @@ -624,6 +635,7 @@ public boolean hasUpToDateJSBundleInCache() {
try {
String packageName = mApplicationContext.getPackageName();
PackageInfo thisPackage =
// NULLSAFE_FIXME[Nullable Dereference]
mApplicationContext.getPackageManager().getPackageInfo(packageName, 0);
if (mJSBundleDownloadedFile.lastModified() > thisPackage.lastUpdateTime) {
// Base APK has not been updated since we downloaded JS, but if app is using exopackage
Expand Down Expand Up @@ -663,6 +675,7 @@ private void resetCurrentContext(@Nullable ReactContext reactContext) {
if (mCurrentReactContext != null) {
try {
URL sourceUrl = new URL(getSourceUrl());
// NULLSAFE_FIXME[Nullable Dereference]
String path = sourceUrl.getPath().substring(1); // strip initial slash in path
String host = sourceUrl.getHost();
String scheme = sourceUrl.getProtocol();
Expand Down Expand Up @@ -785,6 +798,7 @@ public void onProgress(
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void onFailure(Exception cause) {
UiThreadUtil.runOnUiThread(
DevSupportManagerBase.this::hideSplitBundleDevLoadingView);
Expand All @@ -793,6 +807,7 @@ public void onFailure(Exception cause) {
},
bundleFile,
bundleUrl,
// NULLSAFE_FIXME[Parameter Not Nullable]
null);
});
}
Expand Down Expand Up @@ -821,6 +836,7 @@ public void isPackagerRunning(final PackagerStatusCallback callback) {
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public @Nullable File downloadBundleResourceFromUrlSync(
final String resourceURL, final File outputFile) {
return mDevServerHelper.downloadBundleResourceFromUrlSync(resourceURL, outputFile);
Expand Down Expand Up @@ -888,6 +904,7 @@ public void onProgress(
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void onFailure(final Exception cause) {
hideDevLoadingView();
if (mBundleDownloadListener != null) {
Expand Down Expand Up @@ -975,6 +992,7 @@ private void reload() {
// start shake gesture detector
if (!mIsShakeDetectorStarted) {
mShakeDetector.start(
// NULLSAFE_FIXME[Parameter Not Nullable]
(SensorManager) mApplicationContext.getSystemService(Context.SENSOR_SERVICE));
mIsShakeDetectorStarted = true;
}
Expand Down Expand Up @@ -1060,6 +1078,7 @@ private static String getReloadAppAction(Context context) {
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public void setPackagerLocationCustomizer(
DevSupportManager.PackagerLocationCustomizer packagerLocationCustomizer) {
mPackagerLocationCustomizer = packagerLocationCustomizer;
Expand All @@ -1071,6 +1090,7 @@ public void setPackagerLocationCustomizer(
}

@Override
// NULLSAFE_FIXME[Inconsistent Subclass Parameter Annotation]
public @Nullable SurfaceDelegate createSurfaceDelegate(String moduleName) {
if (mSurfaceDelegateFactory == null) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.infer.annotation.Assertions;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.common.JavascriptException;
import com.facebook.react.common.annotations.VisibleForTesting;
import java.io.IOException;
Expand All @@ -29,6 +30,7 @@
import okhttp3.WebSocketListener;

/** A wrapper around WebSocketClient that recognizes RN debugging message format. */
@Nullsafe(Nullsafe.Mode.LOCAL)
class JSDebuggerWebSocketClient extends WebSocketListener {

private static final String TAG = "JSDebuggerWebSocketClient";
Expand Down Expand Up @@ -210,7 +212,7 @@ public void onMessage(@Nullable WebSocket webSocket, String text) {
}

@Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
public void onFailure(@Nullable WebSocket webSocket, Throwable t, @Nullable Response response) {
abort("Websocket exception", t);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@

package com.facebook.react.devsupport;

import com.facebook.infer.annotation.Nullsafe;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import okio.Buffer;
import okio.BufferedSource;
import okio.ByteString;

/** Utility class to parse the body of a response of type multipart/mixed. */
@Nullsafe(Nullsafe.Mode.LOCAL)
class MultipartStreamReader {
// Standard line separator for HTTP.
private static final String CRLF = "\r\n";
Expand Down Expand Up @@ -60,7 +63,7 @@ private void emitChunk(Buffer chunk, boolean done, ChunkListener listener) throw
ByteString marker = ByteString.encodeUtf8(CRLF + CRLF);
long indexOfMarker = chunk.indexOf(marker);
if (indexOfMarker == -1) {
listener.onChunkComplete(null, chunk, done);
listener.onChunkComplete(Collections.emptyMap(), chunk, done);
} else {
Buffer headers = new Buffer();
Buffer body = new Buffer();
Expand Down Expand Up @@ -148,6 +151,7 @@ public boolean readAllParts(ChunkListener listener) throws IOException {
Buffer chunk = new Buffer();
content.skip(chunkStart);
content.read(chunk, length);
// NULLSAFE_FIXME[Parameter Not Nullable]
emitProgress(currentHeaders, chunk.size() - currentHeadersLength, true, listener);
emitChunk(chunk, isCloseDelimiter, listener);
currentHeaders = null;
Expand Down
Loading
Loading