chromium/chrome/browser/trusted_vault/trusted_vault_client_android.h

// 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.

#ifndef CHROME_BROWSER_TRUSTED_VAULT_TRUSTED_VAULT_CLIENT_ANDROID_H_
#define CHROME_BROWSER_TRUSTED_VAULT_TRUSTED_VAULT_CLIENT_ANDROID_H_

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

#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/functional/callback.h"
#include "base/observer_list.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/trusted_vault/trusted_vault_client.h"
#include "third_party/abseil-cpp/absl/types/variant.h"

// JNI bridge for a Java implementation of the TrustedVaultClient interface,
// used on Android.
//
// This class must be accessed from the UI thread.
// TODO(crbug.com/40915967): move this class under components/trusted_vault once
// its java counterpart does not have to stay under chrome/android (e.g. its
// dependecy on AppHooks is addressed).
class TrustedVaultClientAndroid : public trusted_vault::TrustedVaultClient {
 public:
  // Callback that returns account information identified by |gaia_id| or an
  // empty CoreAccountInfo if the account is not found.
  using GetAccountInfoByGaiaIdCallback =
      base::RepeatingCallback<CoreAccountInfo(const std::string& gaia_id)>;

  explicit TrustedVaultClientAndroid(
      const GetAccountInfoByGaiaIdCallback& gaia_account_info_by_gaia_id_cb);
  ~TrustedVaultClientAndroid() override;

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

  // Called from Java to notify the completion of a FetchKeys() operation
  // previously initiated from C++ and identified by |request_id|. |gaia_id|
  // must match the user's ID.
  void FetchKeysCompleted(
      JNIEnv* env,
      jint request_id,
      const base::android::JavaParamRef<jstring>& gaia_id,
      const base::android::JavaParamRef<jobjectArray>& keys);

  // Called from Java to notify the completion of a MarkLocalKeysAsStale()
  // operation previously initiated from C++ and identified by |request_id|.
  void MarkLocalKeysAsStaleCompleted(JNIEnv* env,
                                     jint request_id,
                                     jboolean succeeded);

  // Called from Java to notify the completion of a
  // GetIsRecoverabilityDegraded() operation previously initiated from C++ and
  // identified by |request_id|.
  void GetIsRecoverabilityDegradedCompleted(JNIEnv* env,
                                            jint request_id,
                                            jboolean is_degraded);

  // Called from Java to notify the completion of a
  // AddTrustedRecoveryMethod() operation previously initiated from C++ and
  // identified by |request_id|.
  void AddTrustedRecoveryMethodCompleted(JNIEnv* env, jint request_id);

  // Called from Java to notify that the keys in the vault may have changed.
  void NotifyKeysChanged(JNIEnv* env);

  // Called from Java to notify that the recoverability of the vault may have
  // changed.
  void NotifyRecoverabilityChanged(JNIEnv* env);

  // TrustedVaultClient implementation.
  void AddObserver(Observer* observer) override;
  void RemoveObserver(Observer* observer) override;
  void FetchKeys(
      const CoreAccountInfo& account_info,
      base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> cb)
      override;
  void StoreKeys(const std::string& gaia_id,
                 const std::vector<std::vector<uint8_t>>& keys,
                 int last_key_version) override;
  void MarkLocalKeysAsStale(const CoreAccountInfo& account_info,
                            base::OnceCallback<void(bool)> cb) override;
  void GetIsRecoverabilityDegraded(const CoreAccountInfo& account_info,
                                   base::OnceCallback<void(bool)> cb) override;
  void AddTrustedRecoveryMethod(const std::string& gaia_id,
                                const std::vector<uint8_t>& public_key,
                                int method_type_hint,
                                base::OnceClosure cb) override;
  void ClearLocalDataForAccount(const CoreAccountInfo& account_info) override;

 private:
  // Struct representing an in-flight FetchKeys() call invoked from C++.
  struct OngoingFetchKeys {
    OngoingFetchKeys(
        const CoreAccountInfo& account_info,
        base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)>
            callback);
    OngoingFetchKeys(OngoingFetchKeys&&);
    ~OngoingFetchKeys();

    const CoreAccountInfo account_info;
    base::OnceCallback<void(const std::vector<std::vector<uint8_t>>&)> callback;
  };

  // Struct representing an in-flight MarkLocalKeysAsStale() call invoked from
  // C++.
  struct OngoingMarkLocalKeysAsStale {
    explicit OngoingMarkLocalKeysAsStale(
        base::OnceCallback<void(bool)> callback);
    OngoingMarkLocalKeysAsStale(OngoingMarkLocalKeysAsStale&&);
    ~OngoingMarkLocalKeysAsStale();

    base::OnceCallback<void(bool)> callback;
  };

  // Struct representing an in-flight GetIsRecoverabilityDegraded() invoked from
  // C++.
  struct OngoingGetIsRecoverabilityDegraded {
    explicit OngoingGetIsRecoverabilityDegraded(
        base::OnceCallback<void(bool)> callback);
    OngoingGetIsRecoverabilityDegraded(OngoingGetIsRecoverabilityDegraded&&);
    ~OngoingGetIsRecoverabilityDegraded();

    base::OnceCallback<void(bool)> callback;
  };

  // Struct representing an in-flight AddTrustedRecoveryMethod() invoked from
  // C++.
  struct OngoingAddTrustedRecoveryMethod {
    explicit OngoingAddTrustedRecoveryMethod(base::OnceClosure callback);
    OngoingAddTrustedRecoveryMethod(OngoingAddTrustedRecoveryMethod&&);
    ~OngoingAddTrustedRecoveryMethod();

    base::OnceClosure callback;
  };

  using RequestId = int32_t;
  using OngoingRequest = absl::variant<OngoingFetchKeys,
                                       OngoingMarkLocalKeysAsStale,
                                       OngoingGetIsRecoverabilityDegraded,
                                       OngoingAddTrustedRecoveryMethod>;

  RequestId RegisterNewOngoingRequest(OngoingRequest request);
  OngoingRequest GetAndUnregisterOngoingRequest(RequestId id);

  const GetAccountInfoByGaiaIdCallback gaia_account_info_by_gaia_id_cb_;

  // Each in-flight request gets assigned an auto-increment ID and gets cached
  // in a map, until the response from Java is received.
  RequestId last_request_id_ = 0;
  std::map<RequestId, OngoingRequest> ongoing_requests_;

  base::ObserverList<Observer> observer_list_;
};

#endif  // CHROME_BROWSER_TRUSTED_VAULT_TRUSTED_VAULT_CLIENT_ANDROID_H_