Skip to content

Commit 7e029b0

Browse files
mateoguzmanafacebook-github-bot
authored andcommitted
Modal: FLAG_SECURE not respected in modal dialog (#48317)
Summary: Fixes #38537 Setting `WindowManager.LayoutParams.FLAG_SECURE` in the window flags is not respected in the Android Modal component, causing security issues with screenshots or screen recordings as the content in the modal is visible. The flag works correctly in the rest of the components, see the videos in the linked issue. This PR addresses that by checking whether this flag is set in the current activity and then setting it in the dialog when creating a new one in the `ReactModalHostView`. ## Changelog: [ANDROID][FIXED] - `FLAG_SECURE` not respected in Modal dialog Pull Request resolved: #48317 Test Plan: To test this, you need a physical device as with the emulator the flags don't seem to be respected either. The easiest way to test this in code is by setting the flags in the main activity. You can do so by adding this code snippet: <details> <summary>onCreate in RNTesterApplication.kt</summary> ```kt override fun onCreate() { ReactFontManager.getInstance().addCustomFont(this, "Rubik", R.font.rubik) super.onCreate() ... registerActivityLifecycleCallbacks( object : ActivityLifecycleCallbacks { override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { activity.window.setFlags( WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE ) } override fun onActivityStarted(activity: Activity) {} override fun onActivityResumed(activity: Activity) {} override fun onActivityPaused(activity: Activity) {} override fun onActivityStopped(activity: Activity) {} override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {} override fun onActivityDestroyed(activity: Activity) {} } ) } ``` </details> Then, you can render a simple modal component: <details> <summary>RNTesterPlayground.js</summary> ```tsx function Playground() { const [modalVisible, setModalVisible] = React.useState(false); return ( <> <Modal visible={modalVisible} testID="playground-modal"> <Text testID="inner-text-test-id">Hello World!</Text> <Button title="Close Modal" onPress={() => setModalVisible(false)} /> </Modal> <Button title="Open Modal" onPress={() => { setModalVisible(true); }} /> </> ); } ``` </details> You can then try to record the screen or take screenshots. You will notice that before opening the modal, you won't be able to see anything in the recording, but when opening the modal, the content is visible. I've tried my best to record the before and after the fix, but as the screen recordings will mostly show a black screen, you have to forward a bit in both videos to see the difference. <details> <summary>Before the fix (notice the blank screen and then content visible)</summary> https://github.com/user-attachments/assets/fc5bbe26-d238-425b-90d3-0e43c89ccaac </details> <details> <summary>After the fix (notice all the screen recording is a black screen)</summary> https://github.com/user-attachments/assets/0d6991a0-974b-45c5-8f4a-bf4718c284e6 </details> Reviewed By: cipolleschi Differential Revision: D67368741 Pulled By: alanleedev fbshipit-source-id: 9f31063a9208a6df257da424bf3096bf15a5ddcb
1 parent 3a7aed6 commit 7e029b0

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/modal/ReactModalHostView.kt

+14
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ public class ReactModalHostView(context: ThemedReactContext) :
221221

222222
private fun getCurrentActivity(): Activity? = (context as ThemedReactContext).currentActivity
223223

224+
private fun isFlagSecureSet(activity: Activity?): Boolean {
225+
if (activity == null) {
226+
return false
227+
}
228+
229+
val flags = activity.window.attributes.flags
230+
return (flags and WindowManager.LayoutParams.FLAG_SECURE) != 0
231+
}
232+
224233
/**
225234
* showOrUpdate will display the Dialog. It is called by the manager once all properties are set
226235
* because we need to know all of them before creating the Dialog. It is also smart during updates
@@ -294,6 +303,11 @@ public class ReactModalHostView(context: ThemedReactContext) :
294303
if (hardwareAccelerated) {
295304
newDialog.window?.addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
296305
}
306+
val flagSecureSet = isFlagSecureSet(currentActivity)
307+
if (flagSecureSet) {
308+
newDialog.window?.setFlags(
309+
WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
310+
}
297311
if (currentActivity?.isFinishing == false) {
298312
newDialog.show()
299313
updateSystemAppearance()

0 commit comments

Comments
 (0)