1 /*
2 * Copyright (c) 2024 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 "tone_attrs_napi.h"
17 
18 #include "system_sound_log.h"
19 #include "common_napi.h"
20 
21 #include "tokenid_kit.h"
22 #include "ipc_skeleton.h"
23 #include "access_token.h"
24 #include "accesstoken_kit.h"
25 #include "ringtone_common_napi.h"
26 
27 using OHOS::Security::AccessToken::AccessTokenKit;
28 
29 namespace {
30 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_AUDIO_NAPI, "ToneAttrsNapi"};
31 }
32 
33 namespace OHOS {
34 namespace Media {
35 
36 thread_local napi_ref ToneAttrsNapi::sConstructor_ = nullptr;
37 std::shared_ptr<ToneAttrs> ToneAttrsNapi::sToneAttrs_ = nullptr;
38 
ToneAttrsNapi()39 ToneAttrsNapi::ToneAttrsNapi() : env_(nullptr) {}
40 
41 ToneAttrsNapi::~ToneAttrsNapi() = default;
42 
Init(napi_env env,napi_value exports)43 napi_value ToneAttrsNapi::Init(napi_env env, napi_value exports)
44 {
45     napi_status status;
46     napi_value ctorObj;
47     int32_t refCount = 1;
48 
49     napi_property_descriptor tone_attrs_prop[] = {
50         DECLARE_NAPI_FUNCTION("getTitle", GetTitle),
51         DECLARE_NAPI_FUNCTION("setTitle", SetTitle),
52         DECLARE_NAPI_FUNCTION("getFileName", GetFileName),
53         DECLARE_NAPI_FUNCTION("setFileName", SetFileName),
54         DECLARE_NAPI_FUNCTION("getUri", GetUri),
55         DECLARE_NAPI_FUNCTION("getCustomizedType", GetCustomizedType),
56         DECLARE_NAPI_FUNCTION("setCategory", SetCategory),
57         DECLARE_NAPI_FUNCTION("getCategory", GetCategory),
58     };
59 
60     status = napi_define_class(env, TONE_ATTRS_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
61         Construct, nullptr, sizeof(tone_attrs_prop) / sizeof(tone_attrs_prop[0]),
62         tone_attrs_prop, &ctorObj);
63     if (status == napi_ok) {
64         if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
65             status = napi_set_named_property(env, exports, TONE_ATTRS_NAPI_CLASS_NAME.c_str(), ctorObj);
66             if (status == napi_ok) {
67                 return exports;
68             }
69         }
70     }
71 
72     return nullptr;
73 }
74 
Construct(napi_env env,napi_callback_info info)75 napi_value ToneAttrsNapi::Construct(napi_env env, napi_callback_info info)
76 {
77     napi_status status;
78     napi_value jsThis = nullptr;
79     napi_value thisVar = nullptr;
80 
81     status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
82     if (status == napi_ok) {
83         std::unique_ptr<ToneAttrsNapi> obj = std::make_unique<ToneAttrsNapi>();
84         if (obj != nullptr && thisVar != nullptr) {
85             obj->env_ = env;
86             status = napi_wrap(env, thisVar, static_cast<void*>(obj.get()),
87                                ToneAttrsNapi::Destructor, nullptr, nullptr);
88             if (status == napi_ok) {
89                 obj.release();
90                 return thisVar;
91             }
92         }
93     }
94     MEDIA_LOGE("Failed in ToneAttrsNapi::Construct()!");
95     napi_get_undefined(env, &jsThis);
96     return jsThis;
97 }
98 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)99 void ToneAttrsNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
100 {
101     ToneAttrsNapi *ToneAttrsHelper = reinterpret_cast<ToneAttrsNapi*>(nativeObject);
102     if (ToneAttrsHelper != nullptr) {
103         ObjectRefMap<ToneAttrsNapi>::DecreaseRef(ToneAttrsHelper);
104     }
105 }
106 
NewInstance(napi_env env,std::shared_ptr<ToneAttrs> & nativeToneAttrs,napi_value & out)107 napi_status ToneAttrsNapi::NewInstance(napi_env env, std::shared_ptr<ToneAttrs>& nativeToneAttrs, napi_value& out)
108 {
109     napi_value constructor {};
110     NAPI_CALL_BASE(env, napi_get_reference_value(env, sConstructor_, &constructor), napi_generic_failure);
111     napi_value instance{};
112     NAPI_CALL_BASE(env, napi_new_instance(env, constructor, 0, nullptr, &instance), napi_generic_failure);
113 
114     ToneAttrsNapi* toneAttrsNapi{};
115     NAPI_CALL_BASE(env, napi_unwrap(env, instance, reinterpret_cast<void**>(&toneAttrsNapi)), napi_generic_failure);
116     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, napi_invalid_arg, "toneAttrsNapi is nullptr");
117 
118     toneAttrsNapi->toneAttrs_ = std::move(nativeToneAttrs);
119     out = instance;
120     return napi_ok;
121 }
122 
GetToneAttrs()123 std::shared_ptr<ToneAttrs> ToneAttrsNapi::GetToneAttrs()
124 {
125     return toneAttrs_;
126 }
127 
ThrowErrorAndReturn(napi_env env,const std::string & errMsg,int32_t errCode)128 napi_value ToneAttrsNapi::ThrowErrorAndReturn(napi_env env, const std::string& errMsg, int32_t errCode)
129 {
130     napi_value message = nullptr;
131     napi_value code = nullptr;
132     napi_value errVal = nullptr;
133     napi_value errNameVal = nullptr;
134     napi_value result{};
135     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message);
136     napi_create_error(env, nullptr, message, &errVal);
137     napi_create_int32(env, errCode, &code);
138     napi_set_named_property(env, errVal, "code", code);
139     napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &errNameVal);
140     napi_set_named_property(env, errVal, "BusinessError", errNameVal);
141     napi_throw(env, errVal);
142     napi_get_undefined(env, &result);
143     return result;
144 }
145 
VerifySelfSystemPermission()146 bool ToneAttrsNapi::VerifySelfSystemPermission()
147 {
148     Security::AccessToken::FullTokenID selfTokenID = IPCSkeleton::GetSelfTokenID();
149     auto tokenTypeFlag = Security::AccessToken::AccessTokenKit::GetTokenTypeFlag(static_cast<uint32_t>(selfTokenID));
150     if (tokenTypeFlag == Security::AccessToken::TOKEN_NATIVE ||
151         tokenTypeFlag == Security::AccessToken::TOKEN_SHELL ||
152         Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfTokenID)) {
153         return true;
154     }
155     return false;
156 }
157 
GetTitle(napi_env env,napi_callback_info info)158 napi_value ToneAttrsNapi::GetTitle(napi_env env, napi_callback_info info)
159 {
160     ToneAttrsNapi *toneAttrsNapi = nullptr;
161     napi_value jsThis = nullptr;
162     size_t argc = 0;
163     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
164         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
165         "No system permission");
166 
167     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
168 
169     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
170     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
171     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
172     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
173     napi_value result;
174     napi_create_string_utf8(env,
175         toneAttrsNapi->toneAttrs_->GetTitle().c_str(), NAPI_AUTO_LENGTH, &result);
176     return result;
177 }
178 
SetTitle(napi_env env,napi_callback_info info)179 napi_value ToneAttrsNapi::SetTitle(napi_env env, napi_callback_info info)
180 {
181     ToneAttrsNapi *toneAttrsNapi = nullptr;
182     napi_value jsThis = nullptr;
183     size_t argc = 1;
184     napi_value argv[1] = {};
185     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
186         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
187         "No system permission");
188 
189     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
190 
191     napi_valuetype valueType = napi_undefined;
192     napi_typeof(env, argv[0], &valueType);
193     CHECK_AND_RETURN_RET_LOG(valueType == napi_string, nullptr, "title is not string");
194 
195     std::string toneAttrsTitle = CommonNapi::GetStringArgument(env, argv[0]);
196     CHECK_AND_RETURN_RET_LOG(argc == 1 && !toneAttrsTitle.empty(),
197         ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID_INFO, NAPI_ERR_INPUT_INVALID),
198         "invalid arguments");
199     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
200 
201     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
202     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
203     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
204     toneAttrsNapi->toneAttrs_->SetTitle(toneAttrsTitle);
205     return nullptr;
206 }
207 
GetFileName(napi_env env,napi_callback_info info)208 napi_value ToneAttrsNapi::GetFileName(napi_env env, napi_callback_info info)
209 {
210     ToneAttrsNapi *toneAttrsNapi = nullptr;
211     napi_value jsThis = nullptr;
212     size_t argc = 0;
213     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
214         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
215         "No system permission");
216 
217     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
218     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
219     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
220     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
221     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
222     napi_value result;
223     napi_create_string_utf8(env,
224         toneAttrsNapi->toneAttrs_->GetFileName().c_str(), NAPI_AUTO_LENGTH, &result);
225     return result;
226 }
227 
SetFileName(napi_env env,napi_callback_info info)228 napi_value ToneAttrsNapi::SetFileName(napi_env env, napi_callback_info info)
229 {
230     ToneAttrsNapi *toneAttrsNapi = nullptr;
231     napi_value jsThis = nullptr;
232     size_t argc = 1;
233     napi_value argv[1] = {};
234     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
235         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
236         "No system permission");
237 
238     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
239 
240     napi_valuetype valueType = napi_undefined;
241     napi_typeof(env, argv[0], &valueType);
242     CHECK_AND_RETURN_RET_LOG(valueType == napi_string, nullptr, "filename is not string");
243 
244     std::string toneAttrsFileName = CommonNapi::GetStringArgument(env, argv[0]);
245     CHECK_AND_RETURN_RET_LOG(argc == 1 && !toneAttrsFileName.empty(),
246         ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID_INFO, NAPI_ERR_INPUT_INVALID),
247         "invalid arguments");
248     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
249 
250     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
251     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
252     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
253     toneAttrsNapi->toneAttrs_->SetFileName(toneAttrsFileName);
254     return nullptr;
255 }
256 
GetUri(napi_env env,napi_callback_info info)257 napi_value ToneAttrsNapi::GetUri(napi_env env, napi_callback_info info)
258 {
259     ToneAttrsNapi *toneAttrsNapi = nullptr;
260     napi_value jsThis = nullptr;
261     size_t argc = 0;
262     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
263         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
264         "No system permission");
265 
266     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
267     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
268     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
269     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
270     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
271     napi_value result;
272     napi_create_string_utf8(env,
273         toneAttrsNapi->toneAttrs_->GetUri().c_str(), NAPI_AUTO_LENGTH, &result);
274     return result;
275 }
276 
GetCustomizedType(napi_env env,napi_callback_info info)277 napi_value ToneAttrsNapi::GetCustomizedType(napi_env env, napi_callback_info info)
278 {
279     ToneAttrsNapi *toneAttrsNapi = nullptr;
280     napi_value jsThis = nullptr;
281     size_t argc = 0;
282     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
283         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
284         "No system permission");
285 
286     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
287     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
288     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
289     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
290     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
291     napi_value result;
292     napi_create_int32(env, toneAttrsNapi->toneAttrs_->GetCustomizedType(), &result);
293     return result;
294 }
295 
SetCategory(napi_env env,napi_callback_info info)296 napi_value ToneAttrsNapi::SetCategory(napi_env env, napi_callback_info info)
297 {
298     ToneAttrsNapi *toneAttrsNapi = nullptr;
299     napi_value jsThis = nullptr;
300     size_t argc = 1;
301     napi_value argv[1] = {};
302     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
303         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
304         "No system permission");
305 
306     napi_status status = napi_get_cb_info(env, info, &argc, argv, &jsThis, nullptr);
307 
308     napi_valuetype valueType = napi_undefined;
309     napi_typeof(env, argv[0], &valueType);
310 
311     bool isCategoryValid = false;
312     int32_t toneAttrsCategory = TONE_CATEGORY_INVALID;
313     napi_get_value_int32(env, argv[0], &toneAttrsCategory);
314     if (toneAttrsCategory == TONE_CATEGORY_RINGTONE || toneAttrsCategory == TONE_CATEGORY_TEXT_MESSAGE ||
315         toneAttrsCategory == TONE_CATEGORY_NOTIFICATION || toneAttrsCategory == TONE_CATEGORY_ALARM) {
316         isCategoryValid = true;
317     }
318     CHECK_AND_RETURN_RET_LOG(argc == 1 && isCategoryValid,
319         ThrowErrorAndReturn(env, NAPI_ERR_INPUT_INVALID_INFO, NAPI_ERR_INPUT_INVALID),
320         "invalid arguments");
321     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
322 
323     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
324     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
325     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
326     toneAttrsNapi->toneAttrs_->SetCategory(toneAttrsCategory);
327     return nullptr;
328 }
329 
GetCategory(napi_env env,napi_callback_info info)330 napi_value ToneAttrsNapi::GetCategory(napi_env env, napi_callback_info info)
331 {
332     ToneAttrsNapi *toneAttrsNapi = nullptr;
333     napi_value jsThis = nullptr;
334     size_t argc = 0;
335     CHECK_AND_RETURN_RET_LOG(VerifySelfSystemPermission(),
336         ThrowErrorAndReturn(env, NAPI_ERR_PERMISSION_DENIED_INFO, NAPI_ERR_PERMISSION_DENIED),
337         "No system permission");
338 
339     napi_status status = napi_get_cb_info(env, info, &argc, nullptr, &jsThis, nullptr);
340     CHECK_AND_RETURN_RET_LOG((status == napi_ok) && (jsThis != nullptr), nullptr, "jsThis is nullptr");
341     napi_unwrap(env, jsThis, reinterpret_cast<void**>(&toneAttrsNapi));
342     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi != nullptr, nullptr, "toneAttrsNapi is nullptr");
343     CHECK_AND_RETURN_RET_LOG(toneAttrsNapi->toneAttrs_ != nullptr, nullptr, "toneAttrs_ is nullptr");
344     napi_value result;
345     napi_create_int32(env, toneAttrsNapi->toneAttrs_->GetCategory(), &result);
346     return result;
347 }
348 
349 } // namespace Media
350 } // namespace OHOS