Permalink
base repository: firebase/firebase-cpp-sdk
Failed to load repositories. Confirm that selected base ref is valid, then try again.
base: main
Choose a base ref
...
head repository: firebase/firebase-cpp-sdk
Failed to load repositories. Confirm that selected head ref is valid, then try again.
compare: refactor-swizzling-without-classlist
Choose a head ref
  • 7 commits
  • 4 files changed
  • 1 contributor

Commits on Jun 18, 2025

  1. Refactor ForEachAppDelegateClass for iOS to use swizzling

    This commit refactors the `ForEachAppDelegateClass` function in
    `app/src/util_ios.mm`. Instead of scanning all runtime classes to find
    UIApplicationDelegate implementers, it now relies on method swizzling.
    
    The `[UIApplication setDelegate:]` method is swizzled at startup.
    When `setDelegate:` is called, the class of the actual application
    delegate is captured and stored globally (static to the .mm file).
    
    `ForEachAppDelegateClass` now uses this stored class. If it's called
    before `setDelegate:` has been invoked, the block passed to
    `ForEachAppDelegateClass` is queued. This queued block is then executed
    once the delegate is set via the swizzled `setDelegate:` method.
    
    This approach is more efficient and directly targets the actual
    App Delegate class used by the application.
    
    Key changes:
    - Added `Firebase_setDelegate` C function as the swizzled implementation.
    - Introduced `UIApplication(FirebaseAppDelegateSwizzling)` category with a
      `+load` method to perform the swizzling.
    - Uses `method_setImplementation` for swizzling and stores the original IMP.
    - Global static variables `g_app_delegate_class`,
      `g_original_setDelegate_imp`, and `g_pending_app_delegate_block`
      manage the state within `util_ios.mm`.
    - Modified `ForEachAppDelegateClass` to use the new mechanism and queue
      blocks if the delegate is not yet known.
    @google-labs-jules
    google-labs-jules[bot] committedJun 18, 2025
    Configuration menu
    Copy the full SHA
    0ca39caView commit details
    Browse the repository at this point in the history
  2. I've tidied up util_ios.mm for you.

    I replaced some logging calls with NSLog for better stability during early app startup.
    
    I also removed some unnecessary comments and unused include statements to keep things clean.
    @google-labs-jules
    google-labs-jules[bot] committedJun 18, 2025
    Configuration menu
    Copy the full SHA
    0648d55View commit details
    Browse the repository at this point in the history
  3. feat: Support multiple pending ForEachAppDelegateClass blocks

    Modified `util_ios.mm` to support queueing multiple blocks (up to 8,
    defined by `MAX_PENDING_APP_DELEGATE_BLOCKS`) if `ForEachAppDelegateClass`
    is called before `[UIApplication setDelegate:]` is invoked.
    
    Changes include:
    - Replaced single pending block storage with a C array of block pointers
      and a counter (`g_pending_app_delegate_blocks` and `g_pending_block_count`).
    - `ForEachAppDelegateClass` now adds blocks to this array if the app
      delegate is not yet known. If the array is full, an error is logged
      and the block is discarded.
    - `Firebase_setDelegate` (the swizzled method) now iterates through all
      pending blocks in the array. If a valid delegate is being set, it
      executes each pending block. If the delegate is being set to nil,
      it clears all pending blocks. The array count is reset in both cases.
    - Added `#define MAX_PENDING_APP_DELEGATE_BLOCKS 8` for configurability.
    @google-labs-jules
    google-labs-jules[bot] committedJun 18, 2025
    Configuration menu
    Copy the full SHA
    09591c7View commit details
    Browse the repository at this point in the history
  4. fixup: Cleanup comments and update RunOnAppDelegate call in messaging

    - I removed extraneous developmental comments from app/src/util_ios.mm
      for better code clarity.
    - I updated a call site of firebase::util::RunOnAppDelegate (formerly
      ForEachAppDelegateClass) in messaging/src/ios/messaging.mm to use
      the new function name.
    @google-labs-jules
    google-labs-jules[bot] committedJun 18, 2025
    Configuration menu
    Copy the full SHA
    848a800View commit details
    Browse the repository at this point in the history
  5. I've addressed your review comments.

    - I updated the documentation for RunOnAppDelegateClasses (formerly RunOnAppDelegate) in app/src/util_ios.h to accurately reflect its new behavior.
    - I renamed RunOnAppDelegate to RunOnAppDelegateClasses in all relevant locations (declaration, definition, internal logs, and call sites in invites and messaging modules) for clarity.
    - I removed the specified extraneous code comments from app/src/util_ios.mm and app/src/invites/ios/invites_ios_startup.mm.
    @google-labs-jules
    google-labs-jules[bot] committedJun 18, 2025
    Configuration menu
    Copy the full SHA
    View commit details
    Browse the repository at this point in the history
  6. fix: Make ClassMethodImplementationCache robust against re-swizzling

    I modified `ClassMethodImplementationCache::ReplaceOrAddMethod` in
    app/src/util_ios.mm to prevent re-swizzling a method if it's already
    swizzled with the target implementation. This is done by checking if the
    current method IMP is identical to the incoming IMP; if so, the function
    returns early. This resolves a recursive call issue observed when App
    Delegate hooks were applied multiple times to the same effective class
    via different GUL-proxied delegate instances.
    
    I also included a final cleanup of specified iterative code comments.
    @google-labs-jules
    google-labs-jules[bot] committedJun 18, 2025
    Configuration menu
    Copy the full SHA
    bde3f09View commit details
    Browse the repository at this point in the history

Commits on Jun 19, 2025

  1. fix: Check superclasses before processing new delegates

    Modified `Firebase_setDelegate` in `app/src/util_ios.mm` to prevent
    redundant processing for delegate classes that are subclasses of already
    seen delegates.
    
    - When `setDelegate:` is called with a `newClass`:
      - It now first iterates through the superclasses of `newClass`. If any
        superclass is found in the `g_seen_delegate_classes` list, `newClass`
        is considered handled, and no further processing (adding to seen list
        or running pending blocks for it) occurs.
      - If no superclass is seen, it checks if `newClass` itself is already
        seen. If so, it's skipped.
      - If `newClass` is genuinely new (neither itself nor any superclass
        already seen), it's added to `g_seen_delegate_classes`, and all
        blocks from `g_pending_app_delegate_blocks` are executed for it.
    - This addresses potential issues with third-party libraries (like GUL)
      that might set their own delegate subclasses, ensuring our hooks
      and blocks run appropriately.
    - Includes cleanup of minor iterative comments.
    @google-labs-jules
    google-labs-jules[bot] committedJun 19, 2025
    Configuration menu
    Copy the full SHA
    7e1338bView commit details
    Browse the repository at this point in the history
Loading