chromium/ios/chrome/browser/ui/settings/password/password_sharing/sharing_status_mediator.mm

// Copyright 2023 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/ui/settings/password/password_sharing/sharing_status_mediator.h"

#import "base/strings/sys_string_conversions.h"
#import "ios/chrome/browser/favicon/model/favicon_loader.h"
#import "ios/chrome/browser/net/model/crurl.h"
#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h"
#import "ios/chrome/browser/signin/model/authentication_service.h"
#import "ios/chrome/browser/signin/model/chrome_account_manager_service.h"
#import "ios/chrome/browser/ui/settings/password/password_sharing/multi_avatar_image_util.h"
#import "ios/chrome/browser/ui/settings/password/password_sharing/recipient_info.h"
#import "ios/chrome/browser/ui/settings/password/password_sharing/sharing_status_consumer.h"
#import "ios/chrome/common/ui/favicon/favicon_constants.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util.h"
#import "url/gurl.h"

namespace {

const CGFloat kProfileImageSize = 60.0;

}

@implementation SharingStatusMediator {
  // Authentication Service to get the user's identity.
  raw_ptr<AuthenticationService> _authService;

  // Service that provides Chrome identities.
  raw_ptr<ChromeAccountManagerService> _accountManagerService;

  // Used to fetch favicon images.
  raw_ptr<FaviconLoader> _faviconLoader;

  // Contains information about the recipients that the user selected to share a
  // password with.
  NSArray<RecipientInfoForIOSDisplay*>* _recipients;

  // Website for which the password is being shared.
  NSString* _website;

  // Url of the site for which the password is being shared.
  GURL _URL;

  // Url which allows to change the password that is being shared. Can be null
  // for Android app credentials.
  std::optional<GURL> _changePasswordURL;
}

- (instancetype)
      initWithAuthService:(AuthenticationService*)authService
    accountManagerService:(ChromeAccountManagerService*)accountManagerService
            faviconLoader:(FaviconLoader*)faviconLoader
               recipients:(NSArray<RecipientInfoForIOSDisplay*>*)recipients
                  website:(NSString*)website
                      URL:(const GURL&)URL
        changePasswordURL:(const std::optional<GURL>&)changePasswordURL {
  self = [super init];
  if (self) {
    _authService = authService;
    _accountManagerService = accountManagerService;
    _faviconLoader = faviconLoader;
    _recipients = recipients;
    _website = website;
    _URL = URL;
    _changePasswordURL = changePasswordURL;
  }
  return self;
}

- (void)setConsumer:(id<SharingStatusConsumer>)consumer {
  if (_consumer == consumer) {
    return;
  }

  _consumer = consumer;
  [_consumer setSenderImage:[self fetchSenderImage]];
  [_consumer setRecipientImage:[self createRecipientImage]];
  [_consumer setSubtitleString:[self subtitleString]];
  [_consumer setFooterString:[self footerString]];
  [_consumer setURL:_URL];
}

#pragma mark - TableViewFaviconDataSource

- (void)faviconForPageURL:(CrURL*)URL
               completion:(void (^)(FaviconAttributes*))completion {
  _faviconLoader->FaviconForPageUrl(
      URL.gurl, kDesiredSmallFaviconSizePt, kMinFaviconSizePt,
      /*fallback_to_google_server=*/false, ^(FaviconAttributes* attributes) {
        completion(attributes);
      });
}

#pragma mark - Private

// Fetches and returns sender's profile image from account manager service.
- (UIImage*)fetchSenderImage {
  id<SystemIdentity> identity =
      _authService->GetPrimaryIdentity(signin::ConsentLevel::kSignin);
  if (identity) {
    return CircularImageFromImage(
        _accountManagerService->GetIdentityAvatarWithIdentity(
            identity, IdentityAvatarSize::SmallSize),
        kProfileImageSize);
  }

  return DefaultSymbolTemplateWithPointSize(kPersonCropCircleSymbol,
                                            kProfileImageSize);
}

// Creates a multi-avatar image of recipients from their profile images.
- (UIImage*)createRecipientImage {
  NSMutableArray<UIImage*>* recipientImages = [NSMutableArray array];
  for (RecipientInfoForIOSDisplay* recipient : _recipients) {
    [recipientImages addObject:recipient.profileImage];
  }

  return CreateMultiAvatarImage(recipientImages, kProfileImageSize);
}

// Creates subtitle string based on the amount of recipients chosen for sharing.
// For one recipient the subtitle contains the name of that recipients, whereas
// for multiple recipients it is replaced with more generic string.
- (NSString*)subtitleString {
  if (_recipients.count == 1) {
    return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
        IDS_IOS_PASSWORD_SHARING_SUCCESS_SUBTITLE,
        base::SysNSStringToUTF16(_recipients[0].fullName),
        base::SysNSStringToUTF16(_website)));
  }

  return base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
      IDS_IOS_PASSWORD_SHARING_SUCCESS_SUBTITLE_MULTIPLE_RECIPIENTS,
      base::SysNSStringToUTF16(_website)));
}

// Creates footer string informing the user how to revoke sharing access.
- (NSString*)footerString {
  return _changePasswordURL.has_value()
             ? base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
                   IDS_IOS_PASSWORD_SHARING_SUCCESS_FOOTNOTE,
                   base::SysNSStringToUTF16(_website)))
             : base::SysUTF16ToNSString(l10n_util::GetStringFUTF16(
                   IDS_IOS_PASSWORD_SHARING_SUCCESS_FOOTNOTE_ANDROID_APP,
                   base::SysNSStringToUTF16(_website)));
}

@end