1 /*
2 * Copyright (c) 2023 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 #include "napi_push.h"
16
17 #include "ans_inner_errors.h"
18 #include "common.h"
19 #include "ipc_skeleton.h"
20 #include "js_error_utils.h"
21 #include "js_runtime_utils.h"
22 #include "tokenid_kit.h"
23 #include "napi_common_util.h"
24
25 namespace OHOS {
26 namespace NotificationNapi {
27 namespace {
28 constexpr size_t ARGC_ONE = 1;
29 constexpr size_t ARGC_TWO = 2;
30 constexpr size_t ARGC_THREE = 3;
31 constexpr int32_t INDEX_ZERO = 0;
32 constexpr int32_t INDEX_ONE = 1;
33 constexpr int32_t INDEX_TWO = 2;
34 } // namespace
35 using namespace OHOS::AbilityRuntime;
36
Finalizer(napi_env env,void * data,void * hint)37 void NapiPush::Finalizer(napi_env env, void *data, void *hint)
38 {
39 ANS_LOGD("called");
40 delete static_cast<NapiPush *>(data);
41 }
42
RegisterPushCallback(napi_env env,napi_callback_info info)43 napi_value NapiPush::RegisterPushCallback(napi_env env, napi_callback_info info)
44 {
45 NapiPush *me = CheckParamsAndGetThis<NapiPush>(env, info);
46 if (me == nullptr) {
47 Common::NapiThrow(env, ERROR_PARAM_INVALID);
48 return nullptr;
49 }
50 return me->OnRegisterPushCallback(env, info);
51 }
52
UnregisterPushCallback(napi_env env,napi_callback_info info)53 napi_value NapiPush::UnregisterPushCallback(napi_env env, napi_callback_info info)
54 {
55 NapiPush *me = CheckParamsAndGetThis<NapiPush>(env, info);
56 if (me == nullptr) {
57 Common::NapiThrow(env, ERROR_PARAM_INVALID);
58 return nullptr;
59 }
60 return me->OnUnregisterPushCallback(env, info);
61 }
62
OnRegisterPushCallback(napi_env env,const napi_callback_info info)63 napi_value NapiPush::OnRegisterPushCallback(napi_env env, const napi_callback_info info)
64 {
65 ANS_LOGD("called");
66 napi_value undefined = nullptr;
67 napi_get_undefined(env, &undefined);
68
69 size_t argc = ARGC_THREE;
70 napi_value argv[ARGC_THREE] = {nullptr};
71 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, NULL));
72 if (argc == ARGC_TWO) {
73 ANS_LOGI("Old function param, don't need register.");
74 return undefined;
75 }
76 if (argc < ARGC_THREE) {
77 ANS_LOGE("The param is invalid.");
78 ThrowTooFewParametersError(env);
79 return undefined;
80 }
81
82 std::string type = AppExecFwk::UnwrapStringFromJS(env, argv[INDEX_ZERO]);
83 if (type != "checkNotification") {
84 ANS_LOGE("The type is not checkNotification");
85 ThrowError(env, ERROR_PARAM_INVALID);
86 return undefined;
87 }
88
89 sptr<NotificationCheckRequest> checkRequest = new NotificationCheckRequest();
90 if (ParseCheckRequest(env, argv[INDEX_ONE], checkRequest) == nullptr) {
91 ANS_LOGE("Failed to get check request info from param");
92 ThrowError(env, ERROR_PARAM_INVALID);
93 return undefined;
94 }
95
96 if (!CheckCallerIsSystemApp()) {
97 ThrowError(env, ERROR_NOT_SYSTEM_APP);
98 return undefined;
99 }
100
101 if (jsPushCallBack_ == nullptr) {
102 jsPushCallBack_ = new (std::nothrow) OHOS::Notification::JSPushCallBack(env);
103 if (jsPushCallBack_ == nullptr) {
104 ANS_LOGE("null jsPushCallBack_");
105 ThrowError(env, ERROR_INTERNAL_ERROR);
106 return undefined;
107 }
108 }
109 NotificationConstant::SlotType outSlotType = checkRequest->GetSlotType();
110 jsPushCallBack_->SetJsPushCallBackObject(outSlotType, argv[INDEX_TWO]);
111 auto result = NotificationHelper::RegisterPushCallback(jsPushCallBack_->AsObject(), checkRequest);
112 if (result != ERR_OK) {
113 ANS_LOGE("result: %{public}d", result);
114 ThrowError(env, OHOS::Notification::ErrorToExternal(result));
115 }
116 return undefined;
117 }
118
OnUnregisterPushCallback(napi_env env,const napi_callback_info info)119 napi_value NapiPush::OnUnregisterPushCallback(napi_env env, const napi_callback_info info)
120 {
121 ANS_LOGD("called");
122 napi_value undefined = nullptr;
123 napi_get_undefined(env, &undefined);
124
125 size_t argc = ARGC_TWO;
126 napi_value argv[ARGC_TWO] = {nullptr};
127 napi_value thisVar = nullptr;
128 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
129 if (argc < ARGC_ONE) {
130 ANS_LOGE("The param is invalid.");
131 ThrowTooFewParametersError(env);
132 return undefined;
133 }
134
135 napi_valuetype valueType = napi_undefined;
136 NAPI_CALL(env, napi_typeof(env, argv[INDEX_ZERO], &valueType));
137 if (valueType != napi_string) {
138 ANS_LOGE("Failed to parse type.");
139 ThrowError(env, ERROR_PARAM_INVALID);
140 return undefined;
141 }
142 char str[STR_MAX_SIZE] = {0};
143 size_t strLen = 0;
144 NAPI_CALL(env, napi_get_value_string_utf8(env, argv[INDEX_ZERO], str, STR_MAX_SIZE - 1, &strLen));
145 std::string type = str;
146 if (type != "checkNotification") {
147 ANS_LOGE("The type is not checkNotification");
148 ThrowError(env, ERROR_PARAM_INVALID);
149 return undefined;
150 }
151
152 if (!CheckCallerIsSystemApp()) {
153 ThrowError(env, ERROR_NOT_SYSTEM_APP);
154 return undefined;
155 }
156
157 if (jsPushCallBack_ == nullptr) {
158 ThrowError(env, ERROR_INTERNAL_ERROR);
159 ANS_LOGE("Never registered.");
160 return undefined;
161 }
162
163 if (argc == ARGC_TWO) {
164 if (!jsPushCallBack_->IsEqualPushCallBackObject(argv[INDEX_ONE])) {
165 ANS_LOGE("inconsistent with existing callback");
166 ThrowError(env, ERROR_PARAM_INVALID);
167 return undefined;
168 }
169 }
170
171 NotificationHelper::UnregisterPushCallback();
172 return undefined;
173 }
174
CheckCallerIsSystemApp()175 bool NapiPush::CheckCallerIsSystemApp()
176 {
177 auto selfToken = IPCSkeleton::GetSelfTokenID();
178 if (!Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(selfToken)) {
179 ANS_LOGE("current app is not system app, not allow.");
180 return false;
181 }
182 return true;
183 }
184
ParseCheckRequest(const napi_env & env,const napi_value & obj,sptr<NotificationCheckRequest> & checkRequest)185 napi_value NapiPush::ParseCheckRequest(const napi_env &env,
186 const napi_value &obj, sptr<NotificationCheckRequest> &checkRequest)
187 {
188 ANS_LOGD("start");
189
190 if (!AppExecFwk::IsTypeForNapiValue(env, obj, napi_object)) {
191 ANS_LOGE("Wrong argument type. Object expected.");
192 return nullptr;
193 }
194
195 // contentType
196 int32_t value = 0;
197 if (!AppExecFwk::UnwrapInt32ByPropertyName(env, obj, "contentType", value)) {
198 ANS_LOGE("Failed to get contentType from checkRequest.");
199 return nullptr;
200 }
201 NotificationContent::Type outContentType = NotificationContent::Type::NONE;
202 if (!AnsEnumUtil::ContentTypeJSToC(ContentType(value), outContentType)) {
203 ANS_LOGE("Failed to convert contentType.");
204 return nullptr;
205 }
206 checkRequest->SetContentType(outContentType);
207
208 // slotType
209 if (!AppExecFwk::UnwrapInt32ByPropertyName(env, obj, "slotType", value)) {
210 ANS_LOGE("Failed to get slotType from checkRequest.");
211 return nullptr;
212 }
213 NotificationConstant::SlotType outSlotType = NotificationConstant::SlotType::OTHER;
214 if (!AnsEnumUtil::SlotTypeJSToC(SlotType(value), outSlotType)) {
215 ANS_LOGE("Failed to convert slotType.");
216 return nullptr;
217 }
218 checkRequest->SetSlotType(outSlotType);
219
220 // extraInfoKeys
221 std::vector<std::string> extraInfoKeys;
222 if (!AppExecFwk::UnwrapStringArrayByPropertyName(env, obj, "extraInfoKeys", extraInfoKeys)) {
223 ANS_LOGE("Failed to get extraInfoKeys from checkRequest.");
224 return nullptr;
225 }
226 checkRequest->SetExtraKeys(extraInfoKeys);
227
228 ANS_LOGD("end");
229 return Common::NapiGetNull(env);
230 }
231
232 } // namespace NotificationNapi
233 } // namespace OHOS
234