788a0f8e创建于 2024年11月29日历史提交
/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "plugins/web/webview/android/java/jni/web_data_base_jni.h"

#include <jni.h>

#include "inner_api/plugin_utils_inner.h"
#include "log.h"
#include "plugin_utils.h"

using namespace OHOS::NWebError;

namespace OHOS::Plugin {
namespace {
const char WEB_WEBVIEW_CLASS_NAME[] = "ohos/ace/adapter/capability/web/AceWebPluginBase";

static const JNINativeMethod METHODS[] = {
    { "nativeInitWebDataBase", "()V", reinterpret_cast<void*>(WebDataBaseJni::NativeInit) },
};
static const char METHOD_EXIST_HTTP_AUTH_CREDENTIALS[] = "existHttpAuthCredentials";
static const char METHOD_DELETE_HTTP_AUTH_CREDENTIALS[] = "deleteHttpAuthCredentials";
static const char METHOD_SAVE_HTTP_AUTH_CREDENTIALS[] = "saveHttpAuthCredentials";
static const char METHOD_GET_HTTP_AUTH_CREDENTIALS[] = "getHttpAuthCredentials";

static const char SIGNATURE_EXIST[] = "()Z";
static const char SIGNATURE_DELETE[] = "()V";
static const char SIGNATURE_SAVE[] = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V";
static const char SIGNATURE_GET[] = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;";
struct {
    jmethodID existHttpAuthCredentials;
    jmethodID deleteHttpAuthCredentials;
    jmethodID saveHttpAuthCredentials;
    jmethodID getHttpAuthCredentials;
    jobject globalRef;
} g_webWebviewClass;
}

bool WebDataBaseJni::Register(void* env)
{
    auto* jniEnv = static_cast<JNIEnv*>(env);
    CHECK_NULL_RETURN(jniEnv, false);
    jclass cls = jniEnv->FindClass(WEB_WEBVIEW_CLASS_NAME);
    CHECK_NULL_RETURN(cls, false);
    bool ret = jniEnv->RegisterNatives(cls, METHODS, sizeof(METHODS) / sizeof(METHODS[0])) == 0;
    jniEnv->DeleteLocalRef(cls);
    if (!ret) {
        LOGE("WebDataBaseJni JNI: RegisterNatives fail.");
        return false;
    }
    return true;
}

void WebDataBaseJni::NativeInit(JNIEnv* env, jobject jobj)
{
    LOGI("WebDataBaseJni JNI: NativeInit");
    CHECK_NULL_VOID(env);
    g_webWebviewClass.globalRef = env->NewGlobalRef(jobj);
    CHECK_NULL_VOID(g_webWebviewClass.globalRef);
    jclass cls = env->GetObjectClass(jobj);
    CHECK_NULL_VOID(cls);
    g_webWebviewClass.existHttpAuthCredentials = env->GetMethodID(cls, METHOD_EXIST_HTTP_AUTH_CREDENTIALS,
        SIGNATURE_EXIST);
    CHECK_NULL_VOID(g_webWebviewClass.existHttpAuthCredentials);
    g_webWebviewClass.deleteHttpAuthCredentials = env->GetMethodID(cls, METHOD_DELETE_HTTP_AUTH_CREDENTIALS,
        SIGNATURE_DELETE);
    CHECK_NULL_VOID(g_webWebviewClass.deleteHttpAuthCredentials);
    g_webWebviewClass.saveHttpAuthCredentials = env->GetMethodID(cls, METHOD_SAVE_HTTP_AUTH_CREDENTIALS,
    SIGNATURE_SAVE);
    CHECK_NULL_VOID(g_webWebviewClass.saveHttpAuthCredentials);
    g_webWebviewClass.getHttpAuthCredentials = env->GetMethodID(cls, METHOD_GET_HTTP_AUTH_CREDENTIALS,
    SIGNATURE_GET);
    CHECK_NULL_VOID(g_webWebviewClass.getHttpAuthCredentials);
    env->DeleteLocalRef(cls);
}

bool WebDataBaseJni::ExistHttpAuthCredentials()
{
    auto env = ARKUI_X_Plugin_GetJniEnv();
    CHECK_NULL_RETURN(env, INIT_ERROR);
    jboolean isExist = env->CallBooleanMethod(g_webWebviewClass.globalRef, g_webWebviewClass.existHttpAuthCredentials);
    if (env->ExceptionCheck()) {
        LOGE("WebDataBaseJni JNI: call ExistHttpAuthCredentials has exception");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return false;
    }
    return isExist;
}

ErrCode WebDataBaseJni::DeleteHttpAuthCredentials()
{
    auto env = ARKUI_X_Plugin_GetJniEnv();
    CHECK_NULL_RETURN(env, INIT_ERROR);
    env->CallVoidMethod(g_webWebviewClass.globalRef, g_webWebviewClass.deleteHttpAuthCredentials);
    if (env->ExceptionCheck()) {
        LOGE("WebDataBaseJni JNI: call DeleteHttpAuthCredentials has exception");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return INIT_ERROR;
    }
    return NO_ERROR;
}

ErrCode WebDataBaseJni::SaveHttpAuthCredentials(const std::string& host, const std::string& realm,
    const std::string& username, const char* password)
{
    auto env = ARKUI_X_Plugin_GetJniEnv();
    CHECK_NULL_RETURN(env, INIT_ERROR);
    jstring jHost = env->NewStringUTF(host.c_str());
    CHECK_NULL_RETURN(jHost, INIT_ERROR);
    jstring jRealm = env->NewStringUTF(realm.c_str());
    CHECK_NULL_RETURN(jRealm, INIT_ERROR);
    jstring jUsername = env->NewStringUTF(username.c_str());
    CHECK_NULL_RETURN(jUsername, INIT_ERROR);
    jstring jPassword = env->NewStringUTF(password);
    CHECK_NULL_RETURN(jPassword, INIT_ERROR);
    env->CallVoidMethod(g_webWebviewClass.globalRef, g_webWebviewClass.saveHttpAuthCredentials, jHost, jRealm,
        jUsername, jPassword);
    if (env->ExceptionCheck()) {
        LOGE("WebDataBaseJni JNI: call SaveHttpAuthCredentials has exception");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return INIT_ERROR;
    }
    return NO_ERROR;
}

ErrCode WebDataBaseJni::GetHttpAuthCredentials(const std::string& host, const std::string& realm,
    std::string& username, char* password, uint32_t passwordSize)
{
    auto env = ARKUI_X_Plugin_GetJniEnv();
    CHECK_NULL_RETURN(env, INIT_ERROR);
    jstring jHost = env->NewStringUTF(host.c_str());
    CHECK_NULL_RETURN(jHost, INIT_ERROR);
    jstring jRealm = env->NewStringUTF(realm.c_str());
    CHECK_NULL_RETURN(jRealm, INIT_ERROR);
    jobject jResult = env->CallObjectMethod(g_webWebviewClass.globalRef, g_webWebviewClass.getHttpAuthCredentials, jHost, jRealm);
    if (env->ExceptionCheck()) {
        LOGE("WebDataBaseJni JNI: call GetHttpAuthCredentials has exception");
        env->ExceptionDescribe();
        env->ExceptionClear();
        return INIT_ERROR;
    }
    jclass cls = env->GetObjectClass(jResult);
    CHECK_NULL_RETURN(cls, INIT_ERROR);
    username = GetName(env, cls, jResult);
    std::string passwordResult = GetPassword(env, cls, jResult);
    if (passwordResult.size() > passwordSize) {
        passwordResult = passwordResult.substr(0, passwordSize);
    }
    strcpy(password, passwordResult.c_str());
    return NO_ERROR;
}

std::string WebDataBaseJni::GetName(JNIEnv* env, jclass cls, jobject jobj)
{
    std::string result;
    jmethodID getUsername = env->GetMethodID(cls, "getUsername", "()Ljava/lang/String;");
    CHECK_NULL_RETURN(getUsername, result);
    jstring jResult = static_cast<jstring>(env->CallObjectMethod(jobj, getUsername));
    const char* content = env->GetStringUTFChars(jResult, nullptr);
    if (content != nullptr) {
        result.assign(content);
        env->ReleaseStringUTFChars(jResult, content);
    }
    if (jResult != nullptr) {
        env->DeleteLocalRef(jResult);
    }
    return result;
}

std::string WebDataBaseJni::GetPassword(JNIEnv* env, jclass cls, jobject jobj)
{
    std::string result;
    jmethodID getPassword = env->GetMethodID(cls, "getPassword", "()Ljava/lang/String;");
    CHECK_NULL_RETURN(getPassword, result);
    jstring jResult = static_cast<jstring>(env->CallObjectMethod(jobj, getPassword));
    const char* content = env->GetStringUTFChars(jResult, nullptr);
    if (content != nullptr) {
        result.assign(content);
        env->ReleaseStringUTFChars(jResult, content);
    }
    if (jResult != nullptr) {
        env->DeleteLocalRef(jResult);
    }
    return result;
}
}