chromium/chrome/browser/password_manager/android/generated_password_saved_message_delegate.cc

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

#include "chrome/browser/password_manager/android/generated_password_saved_message_delegate.h"

#include <memory>

#include "base/functional/bind.h"
#include "chrome/browser/android/android_theme_resources.h"
#include "chrome/browser/android/resource_mapper.h"
#include "chrome/browser/password_manager/android/add_username_dialog/add_username_dialog_bridge.h"
#include "chrome/browser/ui/passwords/ui_utils.h"
#include "chrome/grit/generated_resources.h"
#include "components/messages/android/message_dispatcher_bridge.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_contents.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/native_widget_types.h"

GeneratedPasswordSavedMessageDelegate::GeneratedPasswordSavedMessageDelegate()
    : add_username_dialog_factory_(base::BindRepeating(
          []() { return std::make_unique<AddUsernameDialogBridge>(); })) {}

GeneratedPasswordSavedMessageDelegate::GeneratedPasswordSavedMessageDelegate(
    base::PassKey<class GeneratedPasswordSavedMessageDelegateTest>,
    CreateAddUsernameDialogBridge add_username_dialog_factory)
    : add_username_dialog_factory_(std::move(add_username_dialog_factory)) {}

GeneratedPasswordSavedMessageDelegate::
    ~GeneratedPasswordSavedMessageDelegate() {
  DismissPromptInternal();
}

void GeneratedPasswordSavedMessageDelegate::DismissPromptInternal() {
  if (message_ != nullptr) {
    messages::MessageDispatcherBridge::Get()->DismissMessage(
        message_.get(), messages::DismissReason::UNKNOWN);
  }
}

void GeneratedPasswordSavedMessageDelegate::HandleDismissCallback(
    messages::DismissReason dismiss_reason) {
  message_.reset();
  add_username_dialog_bridge_.reset();
  saved_form_.reset();
}

void GeneratedPasswordSavedMessageDelegate::HandleUsernameAddedCallback(
    const std::u16string& username) {
  saved_form_->OnUpdateUsernameFromPrompt(username);
  saved_form_->Save();
}

void GeneratedPasswordSavedMessageDelegate::ShowPrompt(
    content::WebContents* web_contents,
    std::unique_ptr<password_manager::PasswordFormManagerForUI> saved_form) {
  saved_form_ = std::move(saved_form);
  const std::u16string& username =
      saved_form_->GetPendingCredentials().username_value;
  if (username.empty()) {
    ShowAddUsernameDialog(web_contents);
  } else {
    ShowPasswordSavedMessage(web_contents);
  }
}

void GeneratedPasswordSavedMessageDelegate::ShowAddUsernameDialog(
    content::WebContents* web_contents) {
  const std::u16string& password =
      saved_form_->GetPendingCredentials().password_value;

  add_username_dialog_bridge_ = add_username_dialog_factory_.Run();
  // The delegate owns the bridge, so binding callbacks unretained is fine here.
  add_username_dialog_bridge_->ShowAddUsernameDialog(
      web_contents->GetTopLevelNativeWindow(), password,
      base::BindOnce(
          &GeneratedPasswordSavedMessageDelegate::HandleUsernameAddedCallback,
          base::Unretained(this)),
      base::BindOnce(
          &GeneratedPasswordSavedMessageDelegate::HandleDismissCallback,
          base::Unretained(this), messages::DismissReason::UNKNOWN));
}

void GeneratedPasswordSavedMessageDelegate::ShowPasswordSavedMessage(
    content::WebContents* web_contents) {
  message_ = std::make_unique<messages::MessageWrapper>(
      messages::MessageIdentifier::GENERATED_PASSWORD_SAVED,
      base::OnceCallback<void()>(),
      base::BindOnce(
          &GeneratedPasswordSavedMessageDelegate::HandleDismissCallback,
          base::Unretained(this)));

  message_->SetTitle(
      l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_CONFIRM_SAVED_TITLE));

  std::u16string description;
  description = l10n_util::GetStringUTF16(
      IDS_PASSWORD_MANAGER_GENERATED_PASSWORD_SAVED_MESSAGE_DESCRIPTION);

  message_->SetDescription(description);
  message_->SetPrimaryButtonText(l10n_util::GetStringUTF16(IDS_OK));
  message_->SetIconResourceId(ResourceMapper::MapToJavaDrawableId(
      IDR_ANDROID_PASSWORD_MANAGER_LOGO_24DP));
  message_->DisableIconTint();
  messages::MessageDispatcherBridge::Get()->EnqueueMessage(
      message_.get(), web_contents, messages::MessageScopeType::NAVIGATION,
      messages::MessagePriority::kNormal);
}