chromium/ios/chrome/browser/ui/settings/password/password_sharing/password_sharing_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/password_sharing_mediator.h"

#import "base/strings/sys_string_conversions.h"
#import "components/password_manager/core/browser/password_form.h"
#import "components/password_manager/core/browser/sharing/password_sender_service.h"
#import "components/password_manager/core/browser/sharing/recipients_fetcher.h"
#import "components/password_manager/core/browser/sharing/recipients_fetcher_impl.h"
#import "components/password_manager/core/browser/ui/credential_ui_entry.h"
#import "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
#import "components/signin/public/identity_manager/identity_manager.h"
#import "ios/chrome/app/tests_hook.h"
#import "ios/chrome/browser/ui/settings/password/password_sharing/password_sharing_mediator_delegate.h"
#import "ios/chrome/browser/ui/settings/password/password_sharing/recipient_info.h"
#import "ios/chrome/common/channel_info.h"
#import "services/network/public/cpp/shared_url_loader_factory.h"

namespace {

using password_manager::FetchFamilyMembersRequestStatus;
using password_manager::RecipientInfo;
using password_manager::RecipientsFetcher;

std::unique_ptr<RecipientsFetcher> CreateRecipientsFetcher(
    scoped_refptr<network::SharedURLLoaderFactory> sharedURLLoaderFactory,
    signin::IdentityManager* identityManager) {
  std::unique_ptr<RecipientsFetcher> test_recipients_fetcher =
      tests_hook::GetOverriddenRecipientsFetcher();
  if (test_recipients_fetcher) {
    return test_recipients_fetcher;
  }
  return std::make_unique<password_manager::RecipientsFetcherImpl>(
      GetChannel(), sharedURLLoaderFactory, identityManager);
}

}  // namespace

@interface PasswordSharingMediator () {
  // Fetches information about the potential sharing recipients of the user.
  std::unique_ptr<RecipientsFetcher> _recipientsFetcher;

  // Sends passwords to specified recipients.
  raw_ptr<password_manager::PasswordSenderService> _passwordSenderService;

  // Service providing a view on user's saved passwords.
  raw_ptr<password_manager::SavedPasswordsPresenter> _savedPasswordsPresenter;
}

@property(nonatomic, weak) id<PasswordSharingMediatorDelegate> delegate;

@end

@implementation PasswordSharingMediator

- (instancetype)initWithDelegate:(id<PasswordSharingMediatorDelegate>)delegate
          sharedURLLoaderFactory:
              (scoped_refptr<network::SharedURLLoaderFactory>)
                  sharedURLLoaderFactory
                 identityManager:(signin::IdentityManager*)identityManager
         savedPasswordsPresenter:
             (password_manager::SavedPasswordsPresenter*)savedPasswordsPresenter
           passwordSenderService:
               (password_manager::PasswordSenderService*)passwordSenderService {
  self = [super init];
  if (self) {
    _delegate = delegate;
    _recipientsFetcher =
        CreateRecipientsFetcher(sharedURLLoaderFactory, identityManager);
    _passwordSenderService = passwordSenderService;
    _savedPasswordsPresenter = savedPasswordsPresenter;

    __weak __typeof__(self) weakSelf = self;
    _recipientsFetcher->FetchFamilyMembers(base::BindOnce(
        ^(std::vector<password_manager::RecipientInfo> familyMembers,
          FetchFamilyMembersRequestStatus status) {
          [weakSelf onFetchFamilyMembers:familyMembers withStatus:status];
        }));
  }
  return self;
}

- (void)sendSelectedCredentialToSelectedRecipients {
  std::vector<password_manager::PasswordForm> passwords =
      _savedPasswordsPresenter->GetCorrespondingPasswordForms(
          self.selectedCredential);
  for (RecipientInfoForIOSDisplay* recipient in self.selectedRecipients) {
    _passwordSenderService->SendPasswords(
        passwords, {.user_id = base::SysNSStringToUTF8(recipient.userID),
                    .public_key = recipient.publicKey});
  }
}

#pragma mark - Private methods

- (void)onFetchFamilyMembers:(std::vector<RecipientInfo>)familyMembers
                  withStatus:(FetchFamilyMembersRequestStatus)status {
  NSMutableArray<RecipientInfoForIOSDisplay*>* familyMembersForIOSDisplay =
      [NSMutableArray array];
  for (const RecipientInfo& familyMember : familyMembers) {
    [familyMembersForIOSDisplay
        addObject:[[RecipientInfoForIOSDisplay alloc]
                      initWithRecipientInfo:familyMember]];
  }
  [self.delegate onFetchFamilyMembers:familyMembersForIOSDisplay
                           withStatus:status];
}

@end