chromium/ios/chrome/browser/overlays/ui_bundled/overlay_coordinator_factory.mm

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/overlays/ui_bundled/overlay_coordinator_factory.h"

#import <ostream>

#import "base/check.h"
#import "base/memory/raw_ptr.h"
#import "base/notreached.h"
#import "ios/chrome/browser/infobars/model/infobar_ios.h"
#import "ios/chrome/browser/infobars/model/infobar_type.h"
#import "ios/chrome/browser/overlays/model/public/default/default_infobar_overlay_request_config.h"
#import "ios/chrome/browser/overlays/model/public/overlay_request_support.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/infobar_banner_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_banner/translate/translate_infobar_placeholder_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_modal/autofill_address_profile/save_address_profile_infobar_modal_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_modal/parcel_tracking/parcel_tracking_infobar_modal_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_modal/passwords/password_infobar_modal_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_modal/permissions/permissions_infobar_modal_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/infobar_modal/translate/translate_infobar_modal_overlay_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/overlay_request_coordinator.h"
#import "ios/chrome/browser/overlays/ui_bundled/web_content_area/alerts/alert_overlay_coordinator.h"

@implementation OverlayRequestCoordinatorFactory {
  raw_ptr<Browser> _browser;
  OverlayModality _modality;
}

- (instancetype)initWithBrowser:(Browser*)browser
                       modality:(OverlayModality)modality {
  if ((self = [super init])) {
    _browser = browser;
    DCHECK(_browser);

    _modality = modality;
  }
  return self;
}

- (BOOL)coordinatorForRequestUsesChildViewController:(OverlayRequest*)request {
  return [[self coordinatorClassForRequest:request]
      showsOverlayUsingChildViewController];
}

- (OverlayRequestCoordinator*)
    newCoordinatorForRequest:(OverlayRequest*)request
                    delegate:(OverlayRequestCoordinatorDelegate*)delegate
          baseViewController:(UIViewController*)baseViewController {
  return [[[self coordinatorClassForRequest:request] alloc]
      initWithBaseViewController:baseViewController
                         browser:_browser
                         request:request
                        delegate:delegate];
}

#pragma mark - Helpers

// Returns the OverlayRequestCoordinator subclass responsible for showing
// `request`'s overlay UI.
// TODO(crbug.com/40268990): Clean the switch when the default flow is added.
- (Class)coordinatorClassForRequest:(OverlayRequest*)request {
  if (DefaultInfobarOverlayRequestConfig::RequestSupport()->IsRequestSupported(
          request)) {
    DefaultInfobarOverlayRequestConfig* config =
        request->GetConfig<DefaultInfobarOverlayRequestConfig>();
    if (!config->delegate()) {
      // This happens when the browser is killed.
      return nil;
    }
    return [self coordinatorClassForInfobarType:config->infobar_type()];
  }

  switch (_modality) {
    case OverlayModality::kTesting:
      // Use TestOverlayRequestCoordinatorFactory to create factories for
      // OverlayModality::kTesting.
      // TODO(crbug.com/40120484): Remove requirement once modalities are
      // converted to no longer use enums.
      NOTREACHED() << "Received unsupported modality.";
    case OverlayModality::kWebContentArea:
      return [AlertOverlayCoordinator class];
    case OverlayModality::kInfobarBanner:
      if ([TranslateInfobarPlaceholderOverlayCoordinator requestSupport]
              ->IsRequestSupported(request)) {
        return [TranslateInfobarPlaceholderOverlayCoordinator class];
      }
      return [InfobarBannerOverlayCoordinator class];
    case OverlayModality::kInfobarModal:
      if ([SaveAddressProfileInfobarModalOverlayCoordinator requestSupport]
              ->IsRequestSupported(request)) {
        return [SaveAddressProfileInfobarModalOverlayCoordinator class];
      }
      break;
  }
  NOTREACHED() << "Received unsupported request type.";
}

// Returns the coordinator class corresponding to the given `infobarType`.
- (Class)coordinatorClassForInfobarType:(InfobarType)infobarType {
  switch (_modality) {
    case OverlayModality::kTesting:
      // Use TestOverlayRequestCoordinatorFactory to create factories for
      // OverlayModality::kTesting.
      // TODO(crbug.com/40120484): Remove requirement once modalities are
      // converted to no longer use enums.
      NOTREACHED() << "Received unsupported modality.";
    case OverlayModality::kWebContentArea:
      NOTREACHED() << "None implemented yet. Received unsupported modality.";
    case OverlayModality::kInfobarBanner:
      return [InfobarBannerOverlayCoordinator class];
    case OverlayModality::kInfobarModal:
      switch (infobarType) {
        case InfobarType::kInfobarTypePasswordSave:
        case InfobarType::kInfobarTypePasswordUpdate:
          return [PasswordInfobarModalOverlayCoordinator class];
        case InfobarType::kInfobarTypePermissions:
          return [PermissionsInfobarModalOverlayCoordinator class];
        case InfobarType::kInfobarTypeSaveCard:
          return [SaveCardInfobarModalOverlayCoordinator class];
        case InfobarType::kInfobarTypeTranslate:
          return [TranslateInfobarModalOverlayCoordinator class];
        case InfobarType::kInfobarTypeParcelTracking:
          return [ParcelTrackingInfobarModalOverlayCoordinator class];
        default:
          break;
      }
  }
  NOTREACHED() << "Received unsupported infobar type.";
}

@end