1 /*
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "font_manager_addon.h"
17
18 #include "font_define.h"
19 #include "font_hilog.h"
20 #include "font_manager_client.h"
21
22 namespace OHOS {
23 namespace Global {
24 namespace FontManager {
25
26 static constexpr int32_t ARRAY_SUBCRIPTOR_ZERO = 0;
27 static constexpr int32_t ARGS_SIZE_ONE = 1;
Init(napi_env env,napi_value exports)28 napi_value FontManagerAddon::Init(napi_env env, napi_value exports)
29 {
30 napi_property_descriptor properties[] = {
31 DECLARE_NAPI_FUNCTION("installFont", InstallFont),
32 DECLARE_NAPI_FUNCTION("uninstallFont", UninstallFont)
33 };
34 napi_define_properties(env, exports, sizeof(properties) / sizeof(properties[0]), properties);
35 return exports;
36 }
37
GetCallbackErrorCode(napi_env env,const int32_t errCode,const std::string & errMsg)38 napi_value GetCallbackErrorCode(napi_env env, const int32_t errCode, const std::string &errMsg)
39 {
40 napi_value error = nullptr;
41 napi_value eCode = nullptr;
42 napi_value eMsg = nullptr;
43 napi_create_int32(env, errCode, &eCode);
44 napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &eMsg);
45 napi_create_object(env, &error);
46 napi_set_named_property(env, error, "code", eCode);
47 napi_set_named_property(env, error, "message", eMsg);
48 return error;
49 }
50
Complete(napi_env env,napi_status status,void * data)51 void FontManagerAddon::Complete(napi_env env, napi_status status, void* data)
52 {
53 if (data == nullptr) {
54 return;
55 }
56 FontNapiCallback *fontNapiCallback = static_cast<FontNapiCallback*>(data);
57 if (fontNapiCallback == nullptr) {
58 return;
59 }
60 napi_value finalResult = nullptr;
61 napi_status ret = napi_create_int32(env, fontNapiCallback->errCode_, &finalResult);
62 if (ret != napi_ok) {
63 FONT_LOGE("InstallFont: create int result failed");
64 fontNapiCallback->success_ = false;
65 }
66
67 napi_value result[] = { nullptr, nullptr };
68 if (fontNapiCallback->success_) {
69 napi_get_undefined(env, &result[0]);
70 result[1] = finalResult;
71 } else {
72 result[0] = GetCallbackErrorCode(env, fontNapiCallback->errCode_, fontNapiCallback->errMsg_.c_str());
73 napi_get_undefined(env, &result[1]);
74 }
75 ProcessPromiseResult(env, fontNapiCallback, result);
76 napi_delete_async_work(env, fontNapiCallback->work_);
77 delete fontNapiCallback;
78 };
79
ProcessPromiseResult(napi_env env,FontNapiCallback * fontCallback,napi_value (& result)[2])80 void FontManagerAddon::ProcessPromiseResult(napi_env env, FontNapiCallback *fontCallback, napi_value (&result)[2])
81 {
82 if (fontCallback == nullptr) {
83 return;
84 }
85
86 if (fontCallback->success_) {
87 if (napi_resolve_deferred(env, fontCallback->deferred_, result[1]) != napi_ok) {
88 FONT_LOGE("napi_resolve_deferred failed");
89 }
90 } else {
91 if (napi_reject_deferred(env, fontCallback->deferred_, result[0]) != napi_ok) {
92 FONT_LOGE("napi_reject_deferred failed");
93 }
94 }
95 }
96
GetResult(napi_env env,std::unique_ptr<FontNapiCallback> & callback,const std::string & name,napi_async_execute_callback execute)97 napi_value FontManagerAddon::GetResult(napi_env env, std::unique_ptr<FontNapiCallback> &callback,
98 const std::string &name, napi_async_execute_callback execute)
99 {
100 napi_value result = nullptr;
101 if (callback == nullptr) {
102 return result;
103 }
104 napi_create_promise(env, &callback->deferred_, &result);
105
106 napi_value resource = nullptr;
107 napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &resource);
108 if (napi_create_async_work(env, nullptr, resource, execute, FontManagerAddon::Complete,
109 static_cast<void*>(callback.get()), &callback->work_) != napi_ok) {
110 FONT_LOGE("Failed to create async work for %{public}s", name.c_str());
111 return result;
112 }
113 if (napi_queue_async_work_with_qos(env, callback->work_, napi_qos_user_initiated) != napi_ok) {
114 FONT_LOGE("Failed to queue async work for %{public}s", name.c_str());
115 return result;
116 }
117 callback.release();
118 return result;
119 }
120
__anon88854f7c0102(napi_env env, void* data) 121 auto installFontFunc = [](napi_env env, void* data) {
122 if (data == nullptr) {
123 return;
124 }
125
126 FontNapiCallback *callback = static_cast<FontNapiCallback*>(data);
127 if (callback->value_.empty()) {
128 callback->SetErrorMsg("invalid param", ERR_FILE_NOT_EXISTS);
129 return;
130 }
131 int ret = FontManagerClient::InstallFont(callback->value_, callback->errCode_);
132 if (ret != SUCCESS) {
133 callback->SetErrorMsg("Other error.", ERR_INSTALL_FAIL);
134 }
135 if (callback->errCode_ != SUCCESS) {
136 std::string msg = "";
137 switch (callback->errCode_) {
138 case ERR_NO_PERMISSION :
139 msg = "Permission denied.";
140 break;
141 case ERR_NOT_SYSTEM_APP :
142 msg = "Non-system application.";
143 break;
144 case ERR_FILE_NOT_EXISTS :
145 msg = "Font does not exist.";
146 break;
147 case ERR_FILE_VERIFY_FAIL :
148 msg = "Font is not supported.";
149 break;
150 case ERR_COPY_FAIL :
151 msg = "Font file copy failed.";
152 break;
153 case ERR_INSTALLED_ALRADY :
154 msg = "Font file installed.";
155 break;
156 case ERR_MAX_FILE_COUNT :
157 msg = "Exceeded maximum number of installed files.";
158 break;
159 default:
160 msg = "Other error.";
161 }
162 callback->SetErrorMsg(msg, callback->errCode_);
163 }
164 return;
165 };
166
InstallFont(napi_env env,napi_callback_info info)167 napi_value FontManagerAddon::InstallFont(napi_env env, napi_callback_info info)
168 {
169 return ProcessFontByValue(env, info, "InstallFont", installFontFunc);
170 }
171
__anon88854f7c0202(napi_env env, void* data) 172 auto uninstallFontFunc = [](napi_env env, void* data) {
173 if (data == nullptr) {
174 return;
175 }
176
177 FontNapiCallback *callback = static_cast<FontNapiCallback*>(data);
178 if (callback->value_.empty()) {
179 callback->SetErrorMsg("invalid param", ERR_UNINSTALL_FILE_NOT_EXISTS);
180 return;
181 }
182 int ret = FontManagerClient::UninstallFont(callback->value_, callback->errCode_);
183 if (ret != SUCCESS) {
184 callback->SetErrorMsg("Other error.", ERR_UNINSTALL_FAIL);
185 }
186 if (callback->errCode_ != SUCCESS) {
187 std::string msg = "";
188 switch (callback->errCode_) {
189 case ERR_NO_PERMISSION :
190 msg = "Permission denied.";
191 break;
192 case ERR_NOT_SYSTEM_APP :
193 msg = "Non-system application.";
194 break;
195 case ERR_UNINSTALL_FILE_NOT_EXISTS :
196 msg = "Font file does not exist.";
197 break;
198 case ERR_UNINSTALL_REMOVE_FAIL :
199 msg = "Font file delete error.";
200 break;
201 default:
202 msg = "Other error.";
203 }
204 callback->SetErrorMsg(msg, callback->errCode_);
205 }
206 return;
207 };
208
UninstallFont(napi_env env,napi_callback_info info)209 napi_value FontManagerAddon::UninstallFont(napi_env env, napi_callback_info info)
210 {
211 return ProcessFontByValue(env, info, "UninstallFont", uninstallFontFunc);
212 }
213
ProcessFontByValue(napi_env env,napi_callback_info info,const std::string & name,napi_async_execute_callback execute)214 napi_value FontManagerAddon::ProcessFontByValue(
215 napi_env env, napi_callback_info info, const std::string &name, napi_async_execute_callback execute)
216 {
217 FONT_LOGI("ProcessFontByValue, func:%{public}s", name.c_str());
218 size_t argc = ARGS_SIZE_ONE;
219 napi_value argv[ARGS_SIZE_ONE] = {nullptr};
220 napi_value thisVar = nullptr;
221 void *data = nullptr;
222 napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
223 std::unique_ptr<FontNapiCallback> callback = std::make_unique<FontNapiCallback>();
224 callback->value_ = GetResNameOrPath(env, argc, argv);
225 FONT_LOGD("ProcessFontByValue callback->value_= %{public}s", callback->value_.c_str());
226 return GetResult(env, callback, name, execute);
227 }
228
GetResNameOrPath(napi_env env,size_t argc,napi_value * argv)229 std::string FontManagerAddon::GetResNameOrPath(napi_env env, size_t argc, napi_value *argv)
230 {
231 if (argc == 0 || argv == nullptr) {
232 return "";
233 }
234
235 napi_valuetype valuetype;
236 napi_typeof(env, argv[0], &valuetype);
237 if (valuetype != napi_string) {
238 FONT_LOGE("Invalid param, not string");
239 return "";
240 }
241 size_t len = 0;
242 napi_status status = napi_get_value_string_utf8(
243 env, argv[ARRAY_SUBCRIPTOR_ZERO], nullptr, ARRAY_SUBCRIPTOR_ZERO, &len);
244 if (status != napi_ok) {
245 FONT_LOGE("Failed to get font path length");
246 return "";
247 }
248 std::vector<char> buf(len + 1);
249 status = napi_get_value_string_utf8(env, argv[ARRAY_SUBCRIPTOR_ZERO], buf.data(), len + 1, &len);
250 if (status != napi_ok) {
251 FONT_LOGE("Failed to get font file path");
252 return "";
253 }
254 return buf.data();
255 }
256 } // namespace FontManager
257 } // namespace Global
258 } // namespace OHOS