Skip to content

feat(android): add trigger() for onFunction custom-function rules#127

Merged
ethanpschoen merged 11 commits into
justin/feat/cross-activity-lifecyclefrom
ethanpschoen/feat/onfunction-trigger
Jul 15, 2026
Merged

feat(android): add trigger() for onFunction custom-function rules#127
ethanpschoen merged 11 commits into
justin/feat/cross-activity-lifecyclefrom
ethanpschoen/feat/onfunction-trigger

Conversation

@ethanpschoen

@ethanpschoen ethanpschoen commented Jul 14, 2026

Copy link
Copy Markdown

Description of this change

Mirrors the showConsent/showPreferences warm/cold WebView dispatch pattern to fire ketch-tag's onFunction rule trigger (ketch('trigger', 'custom', '', options)). Cold boots defer the trigger command until the tag finishes loading, since a custom function has no boot URL param the way consent/preferences do.

  • KetchWebView.trigger() / Ketch.trigger() with functionName validation
  • Unit tests for functionName validation
  • Integration test covering warm/cold dispatch and invalid-name rejection
  • Demo button wired into both sample apps

Why is this change being made?

  • Chore (non-functional changes)
  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How was this tested? How can the reviewer verify your testing?

Added integration tests, tested using sample app

Related issues

KD-17712

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have evaluated the security impact of this change, and OWASP Secure Coding Practices have been observed.
  • I have informed stakeholders of my changes.

Note

Medium Risk
New WebView JS bridge path with validated function names reduces injection risk, but cold-boot deferral and experience-gating still touch core SDK WebView lifecycle.

Overview
Adds Ketch.trigger(functionName, options) so apps can fire ketch-tag onFunction rules via ketch('trigger', 'custom', …) on the WebView, using the same warm/cold WebView flow as consent and preferences.

On a warm WebView it calls KetchWebView.trigger immediately. On a cold boot it loads the tag without a show-type URL param, stores a pendingTrigger, and runs the JS trigger in onConfigUpdated after the tag loads. Invalid names are rejected up front with a strict allowlist (quotes, whitespace, etc.) so nothing unsafe is interpolated into the JS call. pendingTrigger is cleared on WebView cleanup.

Unit tests cover name validation; integration tests cover invalid rejection, warm dispatch, and cold deferred dispatch. Compose and standard sample apps add demo buttons for demoFunction.

Reviewed by Cursor Bugbot for commit ff649d3. Configure here.

Expose headless bootstrap/config/profile/consent endpoints via HeadlessApiClient,
wire Ketch/KetchSdk surface APIs, refresh index HTML init, and add unit plus
integration test coverage.
Remove tap-outside dismiss plumbing and index HTML touch handlers from
this branch; those belong in run-sample-skills. Branch is off main only
(no native storage commits).
Drop Index.kt, KetchWebView.kt, Events.kt, and WebView flow changes from
the headless branch. Keep HeadlessApiClient, models, KetchSdk/Ketch REST
methods, data center wiring, and integration tests.
ketch_samples/android is only provisioned on the production CDN
(global.ketchcdn.com / KetchDataCenter.US), not the dev/UAT CDN
(dev.ketchcdn.com). testGetBootstrapConfiguration and
testHeadlessColdStartConsentRoundTrip 404 on org-specific endpoints
(/config/ketch_samples/android/boot.json) against UAT, while
testGetLocationReturnsGeoIP incidentally passes since /ip carries no
org/property path segment. Every other reference to this org/property
in the repo (sample apps, WebView-based integration tests, SDK doc
comments) already targets the production CDN.

Introduced in 30c83c7 with no stated rationale for UAT; verified via
git blame and a live re-run against the real CDN (32/34 -> 34/34).
Mirrors the showConsent/showPreferences warm/cold WebView dispatch
pattern to fire ketch-tag's onFunction rule trigger
(ketch('trigger', 'custom', '<name>', options)). Cold boots defer
the trigger command until the tag finishes loading, since a custom
function has no boot URL param the way consent/preferences do.

- KetchWebView.trigger() / Ketch.trigger() with functionName validation
- Unit tests for functionName validation
- Integration test covering warm/cold dispatch and invalid-name rejection
- Demo button wired into both sample apps

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ff649d3. Configure here.

Comment thread ketchsdk/src/main/java/com/ketch/android/Ketch.kt
@ethanpschoen
ethanpschoen requested a review from jboileau99 July 14, 2026 22:07
Base automatically changed from ethanpschoen/feat/headless-sdk to justin/feat/cross-activity-lifecycle July 15, 2026 00:43
@ethanpschoen
ethanpschoen merged commit 05ed820 into justin/feat/cross-activity-lifecycle Jul 15, 2026
3 checks passed
@ethanpschoen
ethanpschoen deleted the ethanpschoen/feat/onfunction-trigger branch July 15, 2026 01:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants