Skip to content

Conversation

NidhiDixit09
Copy link
Collaborator

Reference

EMT-2370 - https://branch.atlassian.net/browse/EMT-2370

Type Of Change

  • New feature (non-breaking change which adds functionality)

cc @BranchMetrics/saas-sdk-devs for visibility.

Copy link
Contributor

matter-code-review bot commented Aug 25, 2025

Code Quality new feature refactoring

Summary By MatterAI MatterAI logo

🔄 What Changed

This Pull Request introduces a new public API setAnonID in the Branch SDK, enabling developers to set a custom anonymous ID for the current user. This method is implemented with robust input validation and thread-safe storage. Concurrently, all code related to BNCAppleReceipt (including its implementation, associated unit tests, and references within BNCRequestFactory and BranchConstants) has been completely removed, streamlining the SDK's codebase. Minor CI/CD updates include correcting an artifact name in the release workflow and upgrading the download-artifact GitHub Action to v5. 🚀

🔍 Impact of the Change

The setAnonID method provides enhanced flexibility for managing anonymous user identification, allowing for more tailored tracking and integration with external systems. The comprehensive removal of BNCAppleReceipt functionality significantly reduces the SDK's footprint and complexity by eliminating unused or deprecated components, leading to a leaner and more maintainable codebase. The CI/CD updates ensure more reliable and up-to-date build and release processes. ✅

📁 Total Files Changed

  • .github/workflows/release.yml: Updated artifact name and download-artifact action version. (2 additions, 2 deletions)
  • Branch-TestBed/Branch-SDK-Tests/BNCAppleReceiptTests.m: Removed unit tests for BNCAppleReceipt. (33 deletions)
  • Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m: Added comprehensive unit tests for the new setAnonID method. (97 additions)
  • Sources/BranchSDK/BNCAppleReceipt.m: Removed the implementation of BNCAppleReceipt. (66 deletions)
  • Sources/BranchSDK/BNCRequestFactory.m: Removed BNCAppleReceipt dependency and related data collection methods. (17 deletions)
  • Sources/BranchSDK/Branch.m: Added the new setAnonID public method with validation and thread safety. (10 additions)
  • Sources/BranchSDK/BranchConstants.m: Removed constants related to Apple Receipt. (2 deletions)
  • Sources/BranchSDK/Private/BNCAppleReceipt.h: Removed the header file for BNCAppleReceipt. (27 deletions)
  • Sources/BranchSDK/Private/BranchConstants.h: Removed constants related to Apple Receipt. (2 deletions)
  • Sources/BranchSDK/Public/Branch.h: Added the declaration for the setAnonID method. (6 additions)

🧪 Test Added

Extensive unit tests for the new Branch.setAnonID method were added in BranchClassTests.m. These tests cover various scenarios, including setting valid string values, updating existing values, handling nil and empty strings gracefully, rejecting non-string objects, verifying behavior with long strings and special characters, and ensuring thread safety during concurrent calls. 🧪

🔒Security Vulnerabilities

No new security vulnerabilities were introduced. The setAnonID method incorporates robust input validation (checking for non-nil and NSString type) and uses @synchronized for thread-safe access to shared preferences, adhering to good defensive programming practices. 🛡️

Tip

Quality Recommendations

  1. Ensure that the removal of BNCAppleReceipt does not impact any downstream analytics or attribution features that might have implicitly relied on its data, and if so, document the new approach.

Tanka Poem ♫

Code flows, clean and bright,
Old receipts fade from sight.
New ID takes hold,
Threads now safely interwove,
Logic's beauty, clear and bold. ✨

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant BranchSDK as Branch SDK
    participant BNCPreferenceHelper as Preference Helper
    participant BranchLogger as Branch Logger

    App->>BranchSDK: Branch.setAnonID(anonID: String)
    activate BranchSDK
    BranchSDK->>BranchSDK: @synchronized(self) block
    alt Valid anonID (non-nil, NSString)
        BranchSDK->>BNCPreferenceHelper: sharedInstance.anonID = anonID
        BNCPreferenceHelper-->>BranchSDK: anonID stored
    else Invalid anonID (nil or non-NSString)
        BranchSDK->>BranchLogger: logWarning("Invalid anonID provided...")
        BranchLogger-->>BranchSDK: Warning logged
    end
    deactivate BranchSDK
Loading

@NidhiDixit09
Copy link
Collaborator Author

/matter review

Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Implementation looks solid with proper timeout validation and comprehensive test coverage. Found one potential race condition in concurrent API loading.

Comment on lines 101 to 106
if (!self.preferenceHelper.appleAttributionTokenChecked) {
self.appleAttributionToken = [BNCSystemObserver appleAttributionToken];
if (self.appleAttributionToken) {
self.preferenceHelper.appleAttributionTokenChecked = YES;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Race condition when setting self.appleAttributionToken from concurrent dispatch queue without synchronization
Fix: Add @synchronized block around property assignment to prevent data races
Impact: Prevents potential crashes or data corruption when multiple threads access this property simultaneously

Suggested change
if (!self.preferenceHelper.appleAttributionTokenChecked) {
self.appleAttributionToken = [BNCSystemObserver appleAttributionToken];
if (self.appleAttributionToken) {
self.preferenceHelper.appleAttributionTokenChecked = YES;
}
}
if (!self.preferenceHelper.appleAttributionTokenChecked) {
NSString *token = [BNCSystemObserver appleAttributionToken];
@synchronized(self) {
self.appleAttributionToken = token;
}
if (self.appleAttributionToken) {
self.preferenceHelper.appleAttributionTokenChecked = YES;
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Resolved: Apple attribution token assignment moved to synchronized block in dispatch queue

Comment on lines 404 to 409
if ([[self.preferenceHelper attributionLevel] isEqualToString:BranchAttributionLevelFull]) {
NSString *odmInfo = [BNCODMInfoCollector instance].odmInfo ;
if (odmInfo) {
[self safeSetValue:odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
if (self.odmInfo) {
[self safeSetValue:self.odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
NSNumber* odmInitDateInNumberFormat = BNCWireFormatFromDate(self.preferenceHelper.odmInfoInitDate);
[self safeSetValue:odmInitDateInNumberFormat forKey:BRANCH_REQUEST_KEY_ODM_FIRST_OPEN_TIMESTAMP onDict:json];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🐛 Bug Fix

Issue: Accessing self.odmInfo without synchronization after concurrent assignment
Fix: Add @synchronized block around property access to ensure thread safety
Impact: Prevents reading potentially corrupted or partially written data

Suggested change
if ([[self.preferenceHelper attributionLevel] isEqualToString:BranchAttributionLevelFull]) {
NSString *odmInfo = [BNCODMInfoCollector instance].odmInfo ;
if (odmInfo) {
[self safeSetValue:odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
if (self.odmInfo) {
[self safeSetValue:self.odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
NSNumber* odmInitDateInNumberFormat = BNCWireFormatFromDate(self.preferenceHelper.odmInfoInitDate);
[self safeSetValue:odmInitDateInNumberFormat forKey:BRANCH_REQUEST_KEY_ODM_FIRST_OPEN_TIMESTAMP onDict:json];
}
if ([[self.preferenceHelper attributionLevel] isEqualToString:BranchAttributionLevelFull]) {
NSString *odmInfo;
@synchronized(self) {
odmInfo = self.odmInfo;
}
if (odmInfo) {
[self safeSetValue:odmInfo forKey:BRANCH_REQUEST_KEY_ODM_INFO onDict:json];
NSNumber* odmInitDateInNumberFormat = BNCWireFormatFromDate(self.preferenceHelper.odmInfoInitDate);
[self safeSetValue:odmInitDateInNumberFormat forKey:BRANCH_REQUEST_KEY_ODM_FIRST_OPEN_TIMESTAMP onDict:json];
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Resolved: ODM info access is now properly synchronized in addODMInfoToJSON method

@NidhiDixit09
Copy link
Collaborator Author

/matter review-full

Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Implementation looks solid with proper timeout validation and thread safety. Found one potential race condition in concurrent dispatch queue usage.

@BranchMetrics BranchMetrics deleted a comment from matter-code-review bot Aug 27, 2025
@gdeluna-branch
Copy link
Contributor

/matter summary

Copy link
Contributor

Summary By MatterAI MatterAI logo

🔄 What Changed

This PR introduces a new setThirdPartyAPIsTimeout method, allowing configuration of timeouts for external API calls like On-Device Conversion (ODM) info and Apple Attribution Token. It refactors the BNCODMInfoCollector to be fully asynchronous, removing blocking calls and centralizing timeout management within BNCRequestFactory. The AppAdsOnDeviceConversion.xcframework dependency has been removed, and CI/CD workflows are updated to use a consistent Xcode version (16.4). Test URLs for BNCAPIServerTest were also updated.

🔍 Impact of the Change

🚀 This change significantly enhances the SDK's performance and responsiveness by making third-party API data collection non-blocking and concurrent. It improves reliability by providing a configurable timeout for external dependencies, preventing potential hangs. The SDK's footprint is reduced by removing an external framework, and CI/CD stability is ensured through consistent Xcode versions. The refactoring streamlines SDK initialization by deferring ODM loading to request creation.

📁 Total Files Changed

  • .github/workflows/pre-release-qa.yml: Updated Xcode version for pre-release QA jobs.
  • .github/workflows/verify.yml: Updated Xcode version for verification jobs.
  • Branch-TestBed/Branch-SDK-Tests/BNCAPIServerTest.m: Updated expected URL for validation service.
  • Branch-TestBed/Branch-SDK-Tests/BNCODMTests.m: Refactored ODM timeout and loading tests to use new async API.
  • Branch-TestBed/Branch-SDK-Tests/BNCPreferenceHelperTests.m: Added tests for thirdPartyAPIsTimeout default and setter/getter.
  • Branch-TestBed/Branch-SDK-Tests/BranchClassTests.m: Added comprehensive tests for Branch.setThirdPartyAPIsTimeout including valid, invalid, and boundary values.
  • Branch-TestBed/Branch-TestBed-CI.xctestplan: Disabled Reflection_ODM_Tests target.
  • Branch-TestBed/Branch-TestBed.xcodeproj/Branch-TestBed.xctestplan: Skipped specific Reflection_ODM_Tests.
  • Branch-TestBed/Reflection_ODM_Tests.xctestplan: Skipped specific Reflection_ODM_Tests.
  • Branch-TestBed/Reflection_ODM_Tests/Framework/.../AppAdsOnDeviceConversion.framework/... (multiple files): Removed AppAdsOnDeviceConversion.xcframework and its related headers/modulemap.
  • Branch-TestBed/Reflection_ODM_Tests/Reflection_ODM_Tests.m: Updated ODM reflection tests to use the new loadODMInfoWithCompletionHandler.
  • Sources/BranchSDK/BNCODMInfoCollector.m: Major refactoring to remove odmInfo property and blocking calls, introducing loadODMInfoWithCompletionHandler.
  • Sources/BranchSDK/Private/BNCODMInfoCollector.h: Updated interface for BNCODMInfoCollector to reflect asynchronous changes.
  • Sources/BranchSDK/BNCPreferenceHelper.m: Added thirdPartyAPIsTimeout property with default value and persistence.
  • Sources/BranchSDK/Public/BNCPreferenceHelper.h: Added thirdPartyAPIsTimeout property declaration.
  • Sources/BranchSDK/BNCRequestFactory.m: Implemented loadDataFromThirdPartyAPIs for concurrent, timeout-controlled fetching of ODM info and Apple Attribution Token.
  • Sources/BranchSDK/BNCSystemObserver.m: Simplified appleAttributionToken method by removing internal timeout logic.
  • Sources/BranchSDK/Branch.m: Removed proactive ODM loading, added setThirdPartyAPIsTimeout static method with validation.
  • Sources/BranchSDK/Public/Branch.h: Added setThirdPartyAPIsTimeout public API declaration.

🧪 Test Added

Extensive tests were added for the new setThirdPartyAPIsTimeout functionality:

  • testThirdPartyAPIsTimeoutDefaultValue: Verifies the default timeout is 0.5 seconds.
  • testThirdPartyAPIsTimeoutSetterGetter: Confirms the timeout can be set and retrieved correctly with various valid values.
  • testBranchSetThirdPartyAPIsTimeout: Checks that the Branch class method correctly updates the preference helper.
  • testBranchSetThirdPartyAPIsTimeoutMultipleValues: Ensures the Branch method handles multiple valid timeout values.
  • testTimeoutIntegrationWithPreferenceHelper: Validates consistency when setting timeouts via Branch and directly on BNCPreferenceHelper.
  • testTimeoutValueConsistency: Confirms the set timeout value remains consistent across multiple reads.
  • testBranchSetThirdPartyAPIsTimeoutInvalidLowValues: Verifies that invalid low timeout values (<= 0) are rejected.
  • testBranchSetThirdPartyAPIsTimeoutInvalidHighValues: Verifies that invalid high timeout values (> 10 seconds) are rejected.
  • testBranchSetThirdPartyAPIsTimeoutBoundaryValues: Tests the behavior at the valid boundaries (0.0001s and 10.0s) and just outside (10.0001s).

🔒Security Vulnerabilities

No new security vulnerabilities were introduced. The changes improve the reliability of external API calls, which can indirectly contribute to a more robust and secure system by preventing hangs or unexpected behavior from third-party services.

@gdeluna-branch
Copy link
Contributor

/matter review

Copy link
Contributor

Simple string formatting change with proper semicolon termination. Code change is minimal and safe.

@NidhiDixit09
Copy link
Collaborator Author

/matter review-full

@BranchMetrics BranchMetrics deleted a comment from matter-code-review bot Aug 29, 2025
@BranchMetrics BranchMetrics deleted a comment from matter-code-review bot Aug 29, 2025
@BranchMetrics BranchMetrics deleted a comment from matter-code-review bot Aug 29, 2025
Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Comprehensive third-party API timeout implementation with proper validation and thread safety. Found several critical bugs in test code and potential race conditions.

Skipped files
  • Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj: Skipped file pattern
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/Info.plist: Skipped file pattern
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion: File hunk diff too large
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Info.plist: Skipped file pattern
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion: File hunk diff too large
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Info.plist: Skipped file pattern

@NidhiDixit09
Copy link
Collaborator Author

/matter review

Copy link
Contributor

@matter-code-review matter-code-review bot left a comment

Choose a reason for hiding this comment

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

Implementation looks solid with proper timeout validation and concurrent API loading. Found one test assertion issue and a potential race condition in property access.

Skipped files
  • Branch-TestBed/Branch-TestBed.xcodeproj/project.pbxproj: Skipped file pattern
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/Info.plist: Skipped file pattern
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion: File hunk diff too large
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64/AppAdsOnDeviceConversion.framework/Info.plist: Skipped file pattern
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/AppAdsOnDeviceConversion: File hunk diff too large
  • Branch-TestBed/Reflection_ODM_Tests/Framework/AppAdsOnDeviceConversion.xcframework/ios-arm64_x86_64-simulator/AppAdsOnDeviceConversion.framework/Info.plist: Skipped file pattern

Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use Matter AI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with Matter AI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use Matter AI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with Matter AI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

1 similar comment
Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use Matter AI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with Matter AI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use Matter AI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with Matter AI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

Copy link
Contributor

Important

PR Review Skipped

PR review skipped as per the configuration setting. Run a manually review by commenting /matter review

💡Tips to use Matter AI

Command List

  • /matter summary: Generate AI Summary for the PR
  • /matter review: Generate AI Reviews for the latest commit in the PR
  • /matter review-full: Generate AI Reviews for the complete PR
  • /matter release-notes: Generate AI release-notes for the PR
  • /matter : Chat with your PR with Matter AI Agent
  • /matter remember : Generate AI memories for the PR
  • /matter explain: Get an explanation of the PR
  • /matter help: Show the list of available commands and documentation
  • Need help? Join our Discord server: https://discord.gg/fJU5DvanU3

@NidhiDixit09 NidhiDixit09 merged commit c98a544 into master Aug 29, 2025
6 of 15 checks passed
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