[Swift] Add support for window.open delegation#82
Conversation
998f068 to
5bff799
Compare
| $0.colorScheme = .automatic | ||
| $0.tintColor = ColorPalette.primaryColor | ||
| $0.preloading.enabled = true | ||
| $0.preloading.enabled = false |
There was a problem hiding this comment.
Disabling preloading in the sample app by default
| switch windowOpen { | ||
| case .default: | ||
| return base | ||
| case .safariViewController: |
There was a problem hiding this comment.
Just for my understanding this means it will default to opening a new webview for unhandled links right?
There was a problem hiding this comment.
This is sample app code. The smart default remains the same and will pull the buyer out of the app and into Safari, but the Sample offers an alternative which opens the link in a Safari webview inside of the app.
I'd like to change the smart default to this going foward
f0a146f to
5759dba
Compare
b059dd3 to
9de70cd
Compare
5628bde to
0eb4b68
Compare
Adds default handling of the UCP window.open delegation. When checkout fires ec.window.open_request, the kit opens the URL via UIApplication and responds with success; if canOpenURL returns false, the kit replies with window_open_rejected_error per spec. The kit advertises window.open in the ec_delegate URL query param and echoes the intersection of merchant-requested ∩ kit-supported delegations in the ec.ready response. Consumers can override the default behaviour via Client.onWindowOpenRequest(_:).
- SwiftFormat: hoist try, wrap arguments/function bodies, extension access control - Replace force-unwraps in CheckoutProtocolURLTests with try #require - Use CapturedURLHolder reference to avoid Swift 6 captured-var warnings in link-dispatch tests - Use XCTestCase expectation+wait pattern for deterministic main-runloop draining
a91994b to
3f6ebf5
Compare
3f6ebf5 to
1393e81
Compare
| // Handle non-HTTP links triggered on external surfaces by opening them with UIApplication | ||
| // Scenarios include: | ||
| // - mailto:, tel: etc | ||
| // - Deep links on offsite payment sites | ||
| // | ||
| if CheckoutURL(from: url).isDeepLink() { | ||
| if UIApplication.shared.canOpenURL(url) { | ||
| UIApplication.shared.open(url) | ||
| OSLogger.shared.debug("Deep link intercepted: \(url.absoluteString) - allowed") | ||
| return decisionHandler(.allow) | ||
| } else { | ||
| OSLogger.shared.debug("Deep link intercepted: \(url.absoluteString) - rejected") | ||
| return decisionHandler(.cancel) | ||
| } |
There was a problem hiding this comment.
Note: This an important change. Previously we delegated this to consumers, where we used the "smart default" to open the URL using UIApplication or allowed consumers to override.
The difference now is that it's handled internally. Link open requests come from checkout via the protocol only.
| } | ||
|
|
||
| extension CheckoutProtocol { | ||
| public static let windowOpen = DelegationDescriptor<WindowOpenRequest, WindowOpenResult>( |
There was a problem hiding this comment.
Cross-platform mismatch with Android PR #107: there WindowOpenRequest, WindowOpenResult, windowOpen, and Client.on(DelegationDescriptor) are internal, and ec.window.open_request short-circuits to the kit default — consumers can't override. Here all four are public (WindowOpen.swift:26,56,78; Client.swift:53) and userContentController tries client?.process (:257) before defaultsClient (:262).
Module split rules out plain internal — @_spi(KitInternal) public is the lightest fix. Worth aligning before merge; once shipped, taking it back is a breaking change.
There was a problem hiding this comment.
These AI generated comments are so hard to read 😵💫
There was a problem hiding this comment.
on Android the equivalent stuff is internal and the kit always handles window.open. Here it's public and the consumer's client gets first dibs, so Swift consumers can override and Android consumers can't. These comes from the feedback on the Android PR. I'm just pointing out disparity.
| /// `UIApplication.shared.open(...)` after a `canOpenURL` check. | ||
| static let defaultsClient = CheckoutProtocol.Client() | ||
| .on(CheckoutProtocol.windowOpen) { request in | ||
| guard UIApplication.shared.canOpenURL(request.url) else { |
There was a problem hiding this comment.
canOpenURL here (and at :295) is gated by LSApplicationQueriesSchemes — if a consumer hasn't declared the scheme in Info.plist, this returns false even when the system has a handler. Same shape kiftio flagged on Android (<queries> brittleness on API 30+). Fix: skip the precheck and use UIApplication.shared.open(_:options:completionHandler:) — the completion reports the real result from the system.
### What changes are you making? Completes the `window.open` UCP delegation handshake on Android, bringing it to parity with [Swift PR #82](#82). The kit advertises `window.open` in the `ec.ready` response, handles `ec.window.open_request` internally via an `ACTION_VIEW` Intent, and narrows the native link-intercept to non-http schemes. The legacy consumer-facing link-click hooks are removed in favor of fully kit-internal handling. ### Before you merge > [!IMPORTANT] > > - [x] I've added tests to support my implementation > - [x] I have read and agree with the [Contribution Guidelines](./CONTRIBUTING.md) > - [x] I have read and agree with the [Code of Conduct](./CODE_OF_CONDUCT.md) > - [ ] I've updated the relevant platform README (`platforms/swift/README.md` and/or `platforms/android/README.md`) --- <details> <summary>Releasing a new Swift version?</summary> - [ ] I have bumped the version in `platforms/swift/ShopifyCheckoutKit.podspec` - [ ] I have bumped the version in `platforms/swift/Sources/ShopifyCheckoutKit/ShopifyCheckoutKit.swift` - [ ] I have updated `platforms/swift/CHANGELOG.md` - [ ] I have updated the SwiftPM/CocoaPods version snippets in `platforms/swift/README.md` (major version only) </details> <details> <summary>Releasing a new Android version?</summary> - [ ] I have bumped the `versionName` in `platforms/android/lib/build.gradle` - [ ] I have updated `platforms/android/CHANGELOG.md` - [ ] I have updated the Gradle/Maven version snippets in `platforms/android/README.md` </details> > [!TIP] > See the [Contributing documentation](./CONTRIBUTING.md) for the full release process per platform.
Adds default handling of the UCP window.open delegation. When checkout fires ec.window.open_request, the kit opens the URL via UIApplication and responds with success; if canOpenURL returns false, the kit replies with window_open_rejected_error per spec.
The kit advertises window.open in the ec_delegate URL query param and echoes the intersection of merchant-requested ∩ kit-supported delegations in the ec.ready response. Consumers can override the default behaviour via Client.onWindowOpenRequest(_:).
Before you merge
Important
platforms/swift/README.mdand/orplatforms/android/README.md)Releasing a new Swift version?
platforms/swift/ShopifyCheckoutKit.podspecplatforms/swift/Sources/ShopifyCheckoutKit/ShopifyCheckoutKit.swiftplatforms/swift/CHANGELOG.mdplatforms/swift/README.md(major version only)Releasing a new Android version?
versionNameinplatforms/android/lib/build.gradleplatforms/android/CHANGELOG.mdplatforms/android/README.mdTip
See the Contributing documentation for the full release process per platform.