chromium/chrome/browser/password_manager/android/password_ui_view_android.h

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

#ifndef CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_UI_VIEW_ANDROID_H_
#define CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_UI_VIEW_ANDROID_H_

#include <stddef.h>

#include <memory>
#include <string>
#include <vector>

#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/affiliations/affiliation_service_factory.h"
#include "chrome/browser/password_entry_edit/android/credential_edit_bridge.h"
#include "chrome/browser/password_manager/account_password_store_factory.h"
#include "chrome/browser/password_manager/profile_password_store_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "components/password_manager/core/browser/password_store/password_store_consumer.h"
#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"

class Profile;

namespace password_manager {
class CredentialProviderInterface;
}

// PasswordUIView for Android, contains jni hooks that allows Android UI to
// display passwords and route UI commands back to SavedPasswordsPresenter.
class PasswordUIViewAndroid
    : public password_manager::SavedPasswordsPresenter::Observer {
 public:
  // Result of transforming a vector of PasswordForms into their CSV
  // description and writing that to disk.
  struct SerializationResult {
    // The number of password entries written. 0 if error encountered.
    int entries_count;

    // The path to the temporary file containing the serialized passwords. Empty
    // if error encountered.
    std::string exported_file_path;

    // The error description recorded after the last write operation. Empty if
    // no error encountered.
    std::string error;
  };

  PasswordUIViewAndroid(JNIEnv* env,
                        const jni_zero::JavaRef<jobject>& obj,
                        Profile* profile);

  PasswordUIViewAndroid(const PasswordUIViewAndroid&) = delete;
  PasswordUIViewAndroid& operator=(const PasswordUIViewAndroid&) = delete;

  ~PasswordUIViewAndroid() override;

  // Calls from Java.
  base::android::ScopedJavaLocalRef<jobject> GetSavedPasswordEntry(
      JNIEnv* env,
      const base::android::JavaRef<jobject>&,
      int index);
  std::string GetSavedPasswordException(JNIEnv* env,
                                        const base::android::JavaRef<jobject>&,
                                        int index);
  void InsertPasswordEntryForTesting(JNIEnv* env,
                                     const std::u16string& origin,
                                     const std::u16string& username,
                                     const std::u16string& password);
  void UpdatePasswordLists(JNIEnv* env, const base::android::JavaRef<jobject>&);
  void HandleRemoveSavedPasswordEntry(JNIEnv* env,
                                      const base::android::JavaRef<jobject>&,
                                      int index);
  void HandleRemoveSavedPasswordException(
      JNIEnv* env,
      const base::android::JavaRef<jobject>&,
      int index);
  void HandleSerializePasswords(
      JNIEnv* env,
      const base::android::JavaRef<jobject>&,
      const std::string& java_target_directory,
      const base::android::JavaRef<jobject>& success_callback,
      const base::android::JavaRef<jobject>& error_callback);
  void HandleShowPasswordEntryEditingView(
      JNIEnv* env,
      const base::android::JavaRef<jobject>& context,
      int index,
      const base::android::JavaParamRef<jobject>& obj);
  void HandleShowBlockedCredentialView(
      JNIEnv* env,
      const base::android::JavaRef<jobject>& context,
      int index,
      const base::android::JavaParamRef<jobject>& obj);
  void ShowMigrationWarning(
      JNIEnv* env,
      const base::android::JavaParamRef<jobject>& activity,
      const base::android::JavaParamRef<jobject>& controller);
  jboolean IsWaitingForPasswordStore(JNIEnv* env,
                                     const base::android::JavaRef<jobject>&);
  // Destroy the native implementation.
  void Destroy(JNIEnv*, const base::android::JavaRef<jobject>&);

  void OnEditUIDismissed();

  void set_export_target_for_testing(
      SerializationResult* export_target_for_testing) {
    export_target_for_testing_ = export_target_for_testing;
  }

  void set_credential_provider_for_testing(
      password_manager::CredentialProviderInterface* provider) {
    credential_provider_for_testing_ = provider;
  }

 private:
  // Possible states in the life of PasswordUIViewAndroid.
  // ALIVE:
  //   * Destroy was not called and no background tasks are pending.
  //   * All data members can be used on the main task runner.
  // ALIVE_SERIALIZATION_PENDING:
  //   * Destroy was not called, password serialization task on another task
  //     runner is running.
  //   * All data members can be used on the main task runner, except for
  //     |saved_passwords_presenter_| which can only be used inside
  //     ObtainAndSerializePasswords, which is being run on a backend task
  //     runner.
  // DELETION_PENDING:
  //   * Destroy() was called, a background task is pending and |this| should
  //     be deleted once the tasks complete.
  //   * This state should not be reached anywhere but in the completion call
  //     of the pending task.
  enum class State { ALIVE, ALIVE_SERIALIZATION_PENDING, DELETION_PENDING };

  // password_manager::SavedPasswordsPresenter::Observer implementation.
  void OnSavedPasswordsChanged(
      const password_manager::PasswordStoreChangeList& changes) override;

  void UpdatePasswordLists();

  // Sends |serialization_result| to Java via |success_callback| or
  // |error_callback|, depending on whether the result is a success or an error.
  void PostSerializedPasswords(
      const base::android::JavaRef<jobject>& success_callback,
      const base::android::JavaRef<jobject>& error_callback,
      SerializationResult serialization_result);

  // The |state_| must only be accessed on the main task runner.
  State state_ = State::ALIVE;

  // If not null, PostSerializedPasswords will write the serialized passwords to
  // |*export_target_for_testing_| instead of passing them to Java. This must
  // remain null in production code.
  raw_ptr<SerializationResult> export_target_for_testing_ = nullptr;

  raw_ptr<Profile> profile_;

  // Pointer to the password store, powering |saved_passwords_presenter_|.
  scoped_refptr<password_manager::PasswordStoreInterface> profile_store_;

  // Manages the list of saved passwords, including updates.
  password_manager::SavedPasswordsPresenter saved_passwords_presenter_;

  // Cached passwords and blocked sites.
  std::vector<password_manager::CredentialUIEntry> passwords_;
  std::vector<password_manager::CredentialUIEntry> blocked_sites_;

  // If not null, passwords for exporting will be obtained from
  // |*credential_provider_for_testing_|, otherwise from
  // |saved_passwords_presenter_|. This must remain null in production code.
  raw_ptr<password_manager::CredentialProviderInterface>
      credential_provider_for_testing_ = nullptr;

  // Java side of UI controller.
  JavaObjectWeakGlobalRef weak_java_ui_controller_;

  // Used to open the view/edit/delete UI.
  std::unique_ptr<CredentialEditBridge> credential_edit_bridge_;
};

#endif  // CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_PASSWORD_UI_VIEW_ANDROID_H_