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

chore(IT Wallet): [SIW-1945] Disable screenshots and recordings on ITW screens #6595

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

gispada
Copy link
Collaborator

@gispada gispada commented Jan 9, 2025

Short description

This PR prevents screenshots and screen recordings in several IT Wallet screens. In order to work on iOS, react-native-flag-secure-android (currently used) has been changed with react-native-screenshot-prevent.

The implementation is the following:

  • On Android it leverages the FLAG_SECURE option;
  • On iOS it creates a hidden secure text field, that renders the screen blank.

List of changes proposed in this pull request

  • Removed react-native-flag-secure-android
  • Installed react-native-screenshot-prevent
  • Added ITW routes to screenBlackList

How to test

Ensure it is not possible to take screenshots or record the content of the screen in the following:

  • CIE pin screen during identification
  • Trust issuer screen
  • Credential preview and detail (including trustmark)

Be sure to disable debug mode, because isAllowedSnapshotCurrentScreen always returns true in debug.

Note

iOS does not seem to offer a direct API to disable screenshots. react-native-screenshot-prevent makes use of a workaround solution, so please test it thoroughly on iOS.

@gispada gispada requested review from ChrisMattew, freddi301 and a team as code owners January 9, 2025 16:13
Copy link
Contributor

github-actions bot commented Jan 9, 2025

Jira Pull Request Link

This Pull Request refers to the following Jira issue SIW-1945

@gispada gispada changed the title Siw 1945 itw prevent screenshots chore(IT Wallet): [SIW-1945] Disable screenshots and recordings on ITW screens Jan 9, 2025
Copy link
Contributor

@LazyAfternoons LazyAfternoons left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest a quick search through the app files to remove any react-native-flag-secure-android leftovers:

  • Manual linking in settings.gradle;
  • Entry in patches.md and the related patch;
  • A type definition under ts/@types/react-native-flag-secure-android.

@mastro993
Copy link
Contributor

On iOS, is still possibile to see the screen content when navigating back. I think we should improve the FlagSecureComponent, allowing the component to know if the screen is completely off the screen.

IMG_0088.MP4

@mastro993
Copy link
Contributor

mastro993 commented Jan 9, 2025

On iOS, is still possibile to see the screen content when navigating back. I think we should improve the FlagSecureComponent, allowing the component to know if the screen is completely off the screen.

IMG_0088.MP4

This happens because the route changes before the screen is correctly unmounted. To solve this we need to rethink how we handle screen capture prevention.
Instead of using a "global" component, we should handle this on a per-component basis, maybe with an hook.

A great example is how the Expo team implemented it. Take a look here: https://github.com/expo/expo/blob/main/packages/expo-screen-capture/src/ScreenCapture.ts#L84

When a component which uses the usePreventScreenCapture hook is mounted, they add a tag to a list. When the component is unmounted, they remove the tag.
If the list contains at least one item, screen recording prevention is enabled. If the list is empty, it is disabled.

I find this approach very simple and effective. I think we should implement something similar!

What do you think?

@gispada
Copy link
Collaborator Author

gispada commented Jan 10, 2025

Good catch @mastro993! I'll work on something like the Expo solution.

Copy link

codecov bot commented Jan 10, 2025

Codecov Report

Attention: Patch coverage is 11.53846% with 23 lines in your changes missing coverage. Please review.

Project coverage is 32.62%. Comparing base (b207270) to head (b833c9a).
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
ts/utils/hooks/usePreventScreenCapture.ts 17.64% 14 Missing ⚠️
...let/identification/screens/cie/ItwCiePinScreen.tsx 0.00% 1 Missing ⚠️
...nce/screens/ItwIssuanceCredentialPreviewScreen.tsx 0.00% 1 Missing ⚠️
...screens/ItwIssuanceCredentialTrustIssuerScreen.tsx 0.00% 1 Missing ⚠️
...eens/ItwPresentationCredentialAttachmentScreen.tsx 0.00% 1 Missing ⚠️
...ion/screens/ItwPresentationCredentialCardModal.tsx 0.00% 1 Missing ⚠️
.../screens/ItwPresentationCredentialDetailScreen.tsx 0.00% 1 Missing ⚠️
...reens/ItwPresentationCredentialFiscalCodeModal.tsx 0.00% 1 Missing ⚠️
...trustmark/screens/ItwCredentialTrustmarkScreen.tsx 0.00% 1 Missing ⚠️
...g/screens/PaymentsOnboardingSelectMethodScreen.tsx 0.00% 1 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (b207270) and HEAD (b833c9a). Click for more details.

HEAD has 8 uploads less than BASE
Flag BASE (b207270) HEAD (b833c9a)
12 4
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           master    #6595       +/-   ##
===========================================
- Coverage   49.30%   32.62%   -16.68%     
===========================================
  Files        1565     1533       -32     
  Lines       32223    31728      -495     
  Branches     7288     7215       -73     
===========================================
- Hits        15887    10351     -5536     
- Misses      16298    21337     +5039     
- Partials       38       40        +2     
Files with missing lines Coverage Δ
...let/identification/screens/cie/ItwCiePinScreen.tsx 14.70% <0.00%> (-0.45%) ⬇️
...nce/screens/ItwIssuanceCredentialPreviewScreen.tsx 9.37% <0.00%> (-0.31%) ⬇️
...screens/ItwIssuanceCredentialTrustIssuerScreen.tsx 8.33% <0.00%> (-25.96%) ⬇️
...eens/ItwPresentationCredentialAttachmentScreen.tsx 12.12% <0.00%> (-0.38%) ⬇️
...ion/screens/ItwPresentationCredentialCardModal.tsx 20.00% <0.00%> (-1.43%) ⬇️
.../screens/ItwPresentationCredentialDetailScreen.tsx 9.37% <0.00%> (-0.31%) ⬇️
...reens/ItwPresentationCredentialFiscalCodeModal.tsx 38.09% <0.00%> (-1.91%) ⬇️
...trustmark/screens/ItwCredentialTrustmarkScreen.tsx 20.00% <0.00%> (-5.00%) ⬇️
...g/screens/PaymentsOnboardingSelectMethodScreen.tsx 4.76% <0.00%> (-0.24%) ⬇️
ts/utils/hooks/usePreventScreenCapture.ts 17.64% <17.64%> (ø)

... and 456 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4c8f237...b833c9a. Read the comment docs.

@gispada
Copy link
Collaborator Author

gispada commented Jan 10, 2025

I refactored the code to use something like the Expo solution. However, in a stack navigator previous components are not unmounted so the useEffect's cleanup function is not called when navigating to the next screen.

I used useFocusEffect instead and it works as expected. However sometimes, especially during iOS swipe back, the blur event is emitted while the animation is still running and for a while the content of the screen is visible again. I solved it with a timeout, but it's not the best solution. What do you think?

*
* @param key An optional key to prevent conflicts when using multiple instances of this hook at the same time.
*/
export function usePreventScreenCapture(key = "default") {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using "default" as the default value, could we use an autogenerated unique ID instead? This would ensure that each component has an unique key.

return () => {
// Here we wait a little after the blur event for navigation transition animations.
// eslint-disable-next-line functional/immutable-data
timeoutRef.current = setTimeout(() => allowScreenCapture(key), 500);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use an useEffect we can avoid adding this timeout. The component is unmounted after the transition. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants