AuthDefaultUIDelegate.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2023 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #if os(iOS) || os(tvOS)
  15. import Foundation
  16. import UIKit
  17. #if COCOAPODS
  18. @_implementationOnly import GoogleUtilities
  19. #else
  20. @_implementationOnly import GoogleUtilities_Environment
  21. #endif
  22. /** @class AuthDefaultUIDelegate
  23. @brief Class responsible for providing a default FIRAuthUIDelegate.
  24. @remarks This class should be used in the case that a UIDelegate was expected and necessary to
  25. continue a given flow, but none was provided.
  26. */
  27. class AuthDefaultUIDelegate: NSObject, AuthUIDelegate {
  28. /** @fn defaultUIDelegate
  29. @brief Returns a default FIRAuthUIDelegate object.
  30. @return The default FIRAuthUIDelegate object.
  31. */
  32. class func defaultUIDelegate() -> AuthUIDelegate? {
  33. if GULAppEnvironmentUtil.isAppExtension() {
  34. // iOS App extensions should not call [UIApplication sharedApplication], even if
  35. // UIApplication responds to it.
  36. return nil
  37. }
  38. // Using reflection here to avoid build errors in extensions.
  39. let sel = NSSelectorFromString("sharedApplication")
  40. guard UIApplication.responds(to: sel),
  41. let rawApplication = UIApplication.perform(sel),
  42. let application = rawApplication.takeUnretainedValue() as? UIApplication else {
  43. return nil
  44. }
  45. var topViewController: UIViewController?
  46. if #available(iOS 13.0, tvOS 13.0, *) {
  47. let connectedScenes = application.connectedScenes
  48. for scene in connectedScenes {
  49. if let windowScene = scene as? UIWindowScene {
  50. for window in windowScene.windows {
  51. if window.isKeyWindow {
  52. topViewController = window.rootViewController
  53. }
  54. }
  55. }
  56. }
  57. } else {
  58. topViewController = application.keyWindow?.rootViewController
  59. }
  60. while true {
  61. if let controller = topViewController?.presentedViewController {
  62. topViewController = controller
  63. } else if let navController = topViewController as? UINavigationController {
  64. topViewController = navController.topViewController
  65. } else if let tabBarController = topViewController as? UITabBarController {
  66. topViewController = tabBarController.selectedViewController
  67. } else {
  68. break
  69. }
  70. }
  71. return AuthDefaultUIDelegate(withViewController: topViewController)
  72. }
  73. init(withViewController viewController: UIViewController?) {
  74. self.viewController = viewController
  75. }
  76. func present(_ viewControllerToPresent: UIViewController, animated flag: Bool,
  77. completion: (() -> Void)? = nil) {
  78. viewController?.present(viewControllerToPresent, animated: flag, completion: completion)
  79. }
  80. func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
  81. viewController?.dismiss(animated: flag, completion: completion)
  82. }
  83. private let viewController: UIViewController?
  84. }
  85. #endif