Skip to content

Add window flags for the payment form and CVV component for payment UI - #305

Open
robert-goheen-cko wants to merge 4 commits into
masterfrom
fix/code-refactor
Open

robert-goheen-cko wants to merge 4 commits into
masterfrom
fix/code-refactor

Conversation

@robert-goheen-cko

Copy link
Copy Markdown

Add a shared helper that manages window flags for the payment form and CVV component while they are shown. It resolves the hosting window (Activity, Fragment, dialog or bottom sheet), shares state between components on the same window, and restores the host app's settings afterwards.

Add unit tests and a README note.

Issue

Issue ticket number and link.

Proposed changes

Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue.

Test Steps

If there's any functionality change, please list a step by step guide of how to verify the changes, and/or upload a screen recording for any visible changes.

For instance:

  1. Go to the main screen
  2. Tap on primary button
  3. Verify the image is shown on the screen

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.

  • Reviewers assigned
  • I have performed a self-review of my code and manual testing
  • Lint and unit tests pass locally with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if applicable)

Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you choose the solution you did and what alternatives you considered, etc...

Add a shared helper that manages window flags for the payment form and
CVV component while they are shown. It resolves the hosting window
(Activity, Fragment, dialog or bottom sheet), shares state between
components on the same window, and restores the host app's settings
afterwards.

Add unit tests and a README note.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Critical lifecycle, dialog-window, and reference-counting defects can leave visible payment data without screenshot protection or keep an old window blocked after the UI is removed.

4 open issues
What changed in this PR

Adds shared screenshot and screen-capture protection for the payment form and CVV component, with per-window tracking intended to preserve the host app’s existing security settings.

Changes:

  • Introduces window resolution, secure-flag management, and shared reference counting.
  • Integrates protection into both payment UI entry points.
  • Adds registry unit tests and documents capture protection.
File Description
README.md Documents capture protection and flag restoration.
frames/​src/​test/​java/​com/​checkout/​frames/​utils/​SecureWindowRegistryTest.kt Tests flag ownership and shared reference counting.
frames/​src/​main/​java/​com/​checkout/​frames/​utils/​SecureWindow.kt Implements window targeting and secure-flag lifecycle management.
frames/​src/​main/​java/​com/​checkout/​frames/​cvvinputfield/​api/​InternalCVVComponentMediator.kt Applies protection to the CVV component.
frames/​src/​main/​java/​com/​checkout/​frames/​api/​PaymentFormMediator.kt Applies protection to the payment form.

Review effort: Balanced

- Follow view attach and detach, so the setting moves with the view.
- Key all window types on the root view, so components share one count.
- Prefer the owning Window for Activity, Compose dialog and
  DialogFragment hosts, and read current layout params on each update.
- Reapply the setting before each frame if the host resets it.
- Fix a JVM signature clash in the unit test and add tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The pre-draw callback can allow sensitive content to render before FLAG_SECURE takes effect, while hidden payment fragments can keep the flag set instead of restoring the host setting.

2 open issues
4 resolved since last review

Review effort: Balanced

- Release while the view is hidden and reacquire before it is drawn
  again, so hidden fragments restore the host's window settings.
- Wrap the window callback for reachable windows, so attribute updates
  keep the setting before they reach the window manager.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Two lifecycle issues can leave screenshot blocking enabled after the payment UI is hidden or removed: clearing the wrong target and a stale pre-draw watcher reapplying FLAG_SECURE.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Restore secure state using the target that acquired it

frames/​src/​main/​java/​com/​checkout/​frames/​utils/​SecureWindow.kt:283

If a WindowSecureTarget acquires first and a RootViewSecureTarget for the same decor view releases last, restoration uses the wrong target. When the root's layout parameters are a separate copy, the final clear leaves Window.attributes secure, so a later window attribute update re-enables screenshot blocking after both components are gone. Retain the acquiring target in Entry and use it for the final clear.

2 resolved since last review

Review effort: Balanced

- Make the pre-draw watcher a no-op once stopped, since an in-progress
  dispatch still calls removed listeners.
- Clear the flag through the target that acquired the window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@robert-goheen-cko

Copy link
Copy Markdown
Author

Re the previously missed issue in the latest review (restoring through the acquiring target): fixed in dc19a11. The registry entry keeps the target that acquired the window and uses it for the final clear. Added a unit test.

@sonarqubecloud

Copy link
Copy Markdown

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Screenshot protection depends on Android callback and rendering timing across Activity and dialog hosts, requiring device-level validation of capture prevention and lifecycle restoration beyond the registry-only JVM tests.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@robert-goheen-cko
robert-goheen-cko marked this pull request as ready for review November 10, 2026 16:30
@robert-goheen-cko
robert-goheen-cko requested a review from a team as a code owner November 10, 2026 16:30
@robert-goheen-cko
robert-goheen-cko requested review from a team November 11, 2026 10:29

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants