chromium/chrome/browser/persisted_state_db/persisted_state_db.cc

// Copyright 2020 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/persisted_state_db/persisted_state_db.h"

#include "base/android/callback_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "chrome/browser/persisted_state_db/session_proto_db_factory.h"
#include "components/commerce/core/proto/persisted_state_db_content.pb.h"
#include "content/public/browser/android/browser_context_handle.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "chrome/browser/tab/jni_headers/LevelDBPersistedDataStorage_jni.h"

namespace {

void OnUpdateCallback(
    const base::android::JavaRef<jobject>& joncomplete_for_testing,
    bool success) {
  if (!success)
    LOG(WARNING) << "There was an error modifying PersistedStateDB";
  // Callback for save and delete is only used in tests for synchronization.
  // Otherwise the callback is a no-op.
  if (joncomplete_for_testing)
    base::android::RunRunnableAndroid(joncomplete_for_testing);
}

void OnLoadCallback(
    const base::android::JavaRef<jobject>& jcallback,
    bool success,
    std::vector<SessionProtoDB<
        persisted_state_db::PersistedStateContentProto>::KeyAndValue> data) {
  if (!success)
    LOG(WARNING) << "There was an error loading from PersistedStateDB";
  base::android::RunObjectCallbackAndroid(
      jcallback, base::android::ToJavaByteArray(
                     base::android::AttachCurrentThread(),
                     data.empty() ? "" : data[0].second.content_data()));
}
}  // namespace

PersistedStateDB::PersistedStateDB(content::BrowserContext* browser_context)
    : proto_db_(
          SessionProtoDBFactory<
              persisted_state_db::PersistedStateContentProto>::GetInstance()
              ->GetForProfile(browser_context)) {}

PersistedStateDB::~PersistedStateDB() = default;

void PersistedStateDB::Save(
    JNIEnv* env,
    const base::android::JavaParamRef<jstring>& jkey,
    const base::android::JavaParamRef<jbyteArray>& jbyte_array,
    const base::android::JavaRef<jobject>& joncomplete_for_testing) {
  const std::string& key = base::android::ConvertJavaStringToUTF8(env, jkey);
  std::string data;
  base::android::JavaByteArrayToString(env, jbyte_array, &data);
  persisted_state_db::PersistedStateContentProto proto;
  proto.set_key(key);
  proto.set_content_data(data);
  proto_db_->InsertContent(
      key, proto,
      base::BindOnce(&OnUpdateCallback,
                     base::android::ScopedJavaGlobalRef<jobject>(
                         joncomplete_for_testing)));
}

void PersistedStateDB::Load(JNIEnv* env,
                            const base::android::JavaParamRef<jstring>& jkey,
                            const base::android::JavaRef<jobject>& jcallback) {
  proto_db_->LoadContentWithPrefix(
      base::android::ConvertJavaStringToUTF8(env, jkey),
      base::BindOnce(&OnLoadCallback,
                     base::android::ScopedJavaGlobalRef<jobject>(jcallback)));
}

void PersistedStateDB::Delete(
    JNIEnv* env,
    const base::android::JavaParamRef<jstring>& jkey,
    const base::android::JavaRef<jobject>& joncomplete_for_testing) {
  proto_db_->DeleteContentWithPrefix(
      base::android::ConvertJavaStringToUTF8(env, jkey),
      base::BindOnce(&OnUpdateCallback,
                     base::android::ScopedJavaGlobalRef<jobject>(
                         joncomplete_for_testing)));
}

void PersistedStateDB::PerformMaintenance(
    JNIEnv* env,
    const base::android::JavaParamRef<jobjectArray>& jkeys_to_keep,
    const base::android::JavaParamRef<jstring>& jkey_substring_to_match,
    const base::android::JavaRef<jobject>& joncomplete_for_testing) {
  std::vector<std::string> keys_to_keep;
  base::android::AppendJavaStringArrayToStringVector(env, jkeys_to_keep,
                                                     &keys_to_keep);
  proto_db_->PerformMaintenance(
      keys_to_keep,
      base::android::ConvertJavaStringToUTF8(jkey_substring_to_match),
      base::BindOnce(&OnUpdateCallback,
                     base::android::ScopedJavaGlobalRef<jobject>(
                         joncomplete_for_testing)));
}

void PersistedStateDB::Destroy(JNIEnv* env) {
  proto_db_->Destroy();
}

static void JNI_LevelDBPersistedDataStorage_Init(
    JNIEnv* env,
    const base::android::JavaParamRef<jobject>& obj,
    const base::android::JavaParamRef<jobject>& jprofile) {
  Java_LevelDBPersistedDataStorage_setNativePtr(
      env, obj,
      reinterpret_cast<intptr_t>(new PersistedStateDB(
          content::BrowserContextFromJavaHandle(jprofile))));
}