• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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