1ce968135Sopenharmony_ci/* 2ce968135Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3ce968135Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4ce968135Sopenharmony_ci * you may not use this file except in compliance with the License. 5ce968135Sopenharmony_ci * You may obtain a copy of the License at 6ce968135Sopenharmony_ci * 7ce968135Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8ce968135Sopenharmony_ci * 9ce968135Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10ce968135Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11ce968135Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12ce968135Sopenharmony_ci * See the License for the specific language governing permissions and 13ce968135Sopenharmony_ci * limitations under the License. 14ce968135Sopenharmony_ci */ 15ce968135Sopenharmony_ci#define LOG_TAG "Call" 16ce968135Sopenharmony_ci#include "call.h" 17ce968135Sopenharmony_ci#include "hilog_wrapper.h" 18ce968135Sopenharmony_ci#include "js_error.h" 19ce968135Sopenharmony_ci#include "wallpaper_js_util.h" 20ce968135Sopenharmony_ci 21ce968135Sopenharmony_cinamespace OHOS::WallpaperNAPI { 22ce968135Sopenharmony_ciCall::Call(napi_env env, napi_callback_info info, std::shared_ptr<Context> context, size_t pos, bool needException) 23ce968135Sopenharmony_ci : env_(env) 24ce968135Sopenharmony_ci{ 25ce968135Sopenharmony_ci context_ = new CallContext(); 26ce968135Sopenharmony_ci size_t argc = WallpaperJSUtil::MAX_ARGC; 27ce968135Sopenharmony_ci napi_value self = nullptr; 28ce968135Sopenharmony_ci napi_value argv[WallpaperJSUtil::MAX_ARGC] = { nullptr }; 29ce968135Sopenharmony_ci NAPI_CALL_RETURN_VOID(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr)); 30ce968135Sopenharmony_ci pos = ((pos == ASYNC_DEFAULT_POS) ? (argc - 1) : pos); 31ce968135Sopenharmony_ci if (pos < argc) { 32ce968135Sopenharmony_ci napi_valuetype valueType = napi_undefined; 33ce968135Sopenharmony_ci napi_typeof(env, argv[pos], &valueType); 34ce968135Sopenharmony_ci if (valueType == napi_function) { 35ce968135Sopenharmony_ci napi_create_reference(env, argv[pos], 1, &context_->callback); 36ce968135Sopenharmony_ci argc = pos; 37ce968135Sopenharmony_ci } else { 38ce968135Sopenharmony_ci context->errCode_ = ErrorThrowType::PARAMETER_ERROR; 39ce968135Sopenharmony_ci context->errMsg_ = std::string(PARAMETER_ERROR_MESSAGE) + "The type of valueType must be function."; 40ce968135Sopenharmony_ci } 41ce968135Sopenharmony_ci } 42ce968135Sopenharmony_ci auto status = (*context)(env, argc, argv, self); 43ce968135Sopenharmony_ci if (status != napi_ok && context->errCode_ != 0 && needException) { 44ce968135Sopenharmony_ci JsError::ThrowError(env, context->errCode_, context->errMsg_); 45ce968135Sopenharmony_ci context->output_ = nullptr; 46ce968135Sopenharmony_ci context->exec_ = nullptr; 47ce968135Sopenharmony_ci } else { 48ce968135Sopenharmony_ci context_->ctx = std::move(context); 49ce968135Sopenharmony_ci napi_create_reference(env, self, 1, &context_->self); 50ce968135Sopenharmony_ci } 51ce968135Sopenharmony_ci} 52ce968135Sopenharmony_ci 53ce968135Sopenharmony_ciCall::~Call() 54ce968135Sopenharmony_ci{ 55ce968135Sopenharmony_ci if (context_ == nullptr) { 56ce968135Sopenharmony_ci return; 57ce968135Sopenharmony_ci } 58ce968135Sopenharmony_ci 59ce968135Sopenharmony_ci DeleteContext(env_, context_); 60ce968135Sopenharmony_ci} 61ce968135Sopenharmony_ci 62ce968135Sopenharmony_cinapi_value Call::AsyncCall(napi_env env, const std::string &resourceName) 63ce968135Sopenharmony_ci{ 64ce968135Sopenharmony_ci if (context_ == nullptr) { 65ce968135Sopenharmony_ci HILOG_ERROR("context_ is null."); 66ce968135Sopenharmony_ci return nullptr; 67ce968135Sopenharmony_ci } 68ce968135Sopenharmony_ci if (context_->ctx == nullptr) { 69ce968135Sopenharmony_ci HILOG_ERROR("context_->ctx is null."); 70ce968135Sopenharmony_ci return nullptr; 71ce968135Sopenharmony_ci } 72ce968135Sopenharmony_ci HILOG_DEBUG("async call exec."); 73ce968135Sopenharmony_ci napi_value promise = nullptr; 74ce968135Sopenharmony_ci if (context_->callback == nullptr) { 75ce968135Sopenharmony_ci napi_create_promise(env, &context_->defer, &promise); 76ce968135Sopenharmony_ci } else { 77ce968135Sopenharmony_ci napi_get_undefined(env, &promise); 78ce968135Sopenharmony_ci } 79ce968135Sopenharmony_ci napi_async_work work = context_->work; 80ce968135Sopenharmony_ci napi_value resource = nullptr; 81ce968135Sopenharmony_ci std::string name = "THEME_" + resourceName; 82ce968135Sopenharmony_ci napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource); 83ce968135Sopenharmony_ci napi_create_async_work(env, nullptr, resource, Call::OnExecute, Call::OnComplete, context_, &work); 84ce968135Sopenharmony_ci context_->work = work; 85ce968135Sopenharmony_ci context_ = nullptr; 86ce968135Sopenharmony_ci napi_queue_async_work_with_qos(env, work, napi_qos_user_initiated); 87ce968135Sopenharmony_ci return promise; 88ce968135Sopenharmony_ci} 89ce968135Sopenharmony_ci 90ce968135Sopenharmony_cinapi_value Call::SyncCall(napi_env env) 91ce968135Sopenharmony_ci{ 92ce968135Sopenharmony_ci if ((context_ == nullptr) || (context_->ctx == nullptr)) { 93ce968135Sopenharmony_ci HILOG_ERROR("context_ or context_->ctx is null."); 94ce968135Sopenharmony_ci return nullptr; 95ce968135Sopenharmony_ci } 96ce968135Sopenharmony_ci Call::OnExecute(env, context_); 97ce968135Sopenharmony_ci napi_value output = nullptr; 98ce968135Sopenharmony_ci napi_status runStatus = (*context_->ctx)(env, &output); 99ce968135Sopenharmony_ci if (runStatus != napi_ok && context_->ctx->errCode_ != 0) { 100ce968135Sopenharmony_ci JsError::ThrowError(env, context_->ctx->errCode_, context_->ctx->errMsg_); 101ce968135Sopenharmony_ci output = nullptr; 102ce968135Sopenharmony_ci } 103ce968135Sopenharmony_ci DeleteContext(env, context_); 104ce968135Sopenharmony_ci context_ = nullptr; 105ce968135Sopenharmony_ci return output; 106ce968135Sopenharmony_ci} 107ce968135Sopenharmony_ci 108ce968135Sopenharmony_civoid Call::OnExecute(napi_env env, void *data) 109ce968135Sopenharmony_ci{ 110ce968135Sopenharmony_ci HILOG_DEBUG("run the async runnable."); 111ce968135Sopenharmony_ci CallContext *context = reinterpret_cast<CallContext *>(data); 112ce968135Sopenharmony_ci context->ctx->Exec(); 113ce968135Sopenharmony_ci} 114ce968135Sopenharmony_ci 115ce968135Sopenharmony_civoid Call::OnComplete(napi_env env, napi_status status, void *data) 116ce968135Sopenharmony_ci{ 117ce968135Sopenharmony_ci HILOG_DEBUG("run the js callback function."); 118ce968135Sopenharmony_ci CallContext *context = reinterpret_cast<CallContext *>(data); 119ce968135Sopenharmony_ci napi_value output = nullptr; 120ce968135Sopenharmony_ci napi_status runStatus = (*context->ctx)(env, &output); 121ce968135Sopenharmony_ci napi_value result[ARG_BUTT] = { 0 }; 122ce968135Sopenharmony_ci HILOG_DEBUG("run the js callback function:status[%{public}d]runStatus[%{public}d]", status, runStatus); 123ce968135Sopenharmony_ci if (status == napi_ok && runStatus == napi_ok) { 124ce968135Sopenharmony_ci napi_get_undefined(env, &result[ARG_ERROR]); 125ce968135Sopenharmony_ci if (output != nullptr) { 126ce968135Sopenharmony_ci HILOG_DEBUG("AsyncCall::OnComplete output != nullptr."); 127ce968135Sopenharmony_ci result[ARG_DATA] = output; 128ce968135Sopenharmony_ci } else { 129ce968135Sopenharmony_ci HILOG_DEBUG("AsyncCall::OnComplete output == nullptr."); 130ce968135Sopenharmony_ci napi_get_undefined(env, &result[ARG_DATA]); 131ce968135Sopenharmony_ci } 132ce968135Sopenharmony_ci } else { 133ce968135Sopenharmony_ci napi_value errCode = nullptr; 134ce968135Sopenharmony_ci napi_value message = nullptr; 135ce968135Sopenharmony_ci std::string errMsg("async call failed"); 136ce968135Sopenharmony_ci if (context->ctx->errCode_ != 0) { 137ce968135Sopenharmony_ci napi_create_int32(env, context->ctx->errCode_, &errCode); 138ce968135Sopenharmony_ci } 139ce968135Sopenharmony_ci if (!context->ctx->errMsg_.empty()) { 140ce968135Sopenharmony_ci errMsg = context->ctx->errMsg_; 141ce968135Sopenharmony_ci } 142ce968135Sopenharmony_ci napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message); 143ce968135Sopenharmony_ci napi_create_error(env, nullptr, message, &result[ARG_ERROR]); 144ce968135Sopenharmony_ci napi_set_named_property(env, result[ARG_ERROR], "code", errCode); 145ce968135Sopenharmony_ci napi_get_undefined(env, &result[ARG_DATA]); 146ce968135Sopenharmony_ci } 147ce968135Sopenharmony_ci HILOG_DEBUG("run the js callback function:(context->defer != nullptr)?[%{public}d]", context->defer != nullptr); 148ce968135Sopenharmony_ci if (context->defer != nullptr) { 149ce968135Sopenharmony_ci // promise 150ce968135Sopenharmony_ci HILOG_DEBUG("Promise to do!"); 151ce968135Sopenharmony_ci if (status == napi_ok && runStatus == napi_ok) { 152ce968135Sopenharmony_ci napi_resolve_deferred(env, context->defer, result[ARG_DATA]); 153ce968135Sopenharmony_ci } else { 154ce968135Sopenharmony_ci napi_reject_deferred(env, context->defer, result[ARG_ERROR]); 155ce968135Sopenharmony_ci } 156ce968135Sopenharmony_ci } else { 157ce968135Sopenharmony_ci // callback 158ce968135Sopenharmony_ci HILOG_DEBUG("Callback to do!"); 159ce968135Sopenharmony_ci napi_value callback = nullptr; 160ce968135Sopenharmony_ci napi_get_reference_value(env, context->callback, &callback); 161ce968135Sopenharmony_ci napi_value returnValue; 162ce968135Sopenharmony_ci napi_call_function(env, nullptr, callback, ARG_BUTT, result, &returnValue); 163ce968135Sopenharmony_ci } 164ce968135Sopenharmony_ci DeleteContext(env, context); 165ce968135Sopenharmony_ci} 166ce968135Sopenharmony_civoid Call::DeleteContext(napi_env env, CallContext *context) 167ce968135Sopenharmony_ci{ 168ce968135Sopenharmony_ci if (env != nullptr) { 169ce968135Sopenharmony_ci napi_delete_reference(env, context->callback); 170ce968135Sopenharmony_ci napi_delete_reference(env, context->self); 171ce968135Sopenharmony_ci napi_delete_async_work(env, context->work); 172ce968135Sopenharmony_ci } 173ce968135Sopenharmony_ci delete context; 174ce968135Sopenharmony_ci} 175ce968135Sopenharmony_ci} // namespace OHOS::WallpaperNAPI