• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "js_continuation_state_manager.h"
17 #include "js_continuation_state_client.h"
18 
19 #include "napi_error_code.h"
20 #include "dtbschedmgr_log.h"
21 #include "iservice_registry.h"
22 #include "system_ability_definition.h"
23 
24 namespace OHOS {
25 namespace DistributedSchedule {
26 using namespace OHOS::AbilityRuntime;
27 using namespace OHOS::AppExecFwk;
28 namespace {
29     const std::string TAG = "JsContinuationStateManager";
30     const std::string BIZTYPE_PREPARE_CONTINUE = "prepareContinue";
31     const std::string CODE_KEY_NAME = "code";
32     const std::string ERR_DMS_WORK_ABNORMALLY_MSG = "the system ability work abnormally.";
33     const int32_t ARG_INDEX_4_CALLBACK_FUNC = 2;
34     const int32_t SUCCESS = 0;
35     const int32_t FAILED = 1;
36     constexpr int32_t ARG_COUNT_TWO = 2;
37     constexpr int32_t ARG_COUNT_THREE = 3;
38     const int32_t CALLBACK_PARAMS_NUM = 2;
39 }
40 
41 std::map<std::string, sptr<DistributedSchedule::JsContinuationStateManagerStub>>
42     JsContinuationStateManager::callbackStubs_;
43 
ContinueStateCallbackOn(napi_env env,napi_callback_info info)44 napi_value JsContinuationStateManager::ContinueStateCallbackOn(napi_env env, napi_callback_info info)
45 {
46     HILOGI("ContinueStateCallbackOn call");
47     napi_value ret = nullptr;
48     int32_t result = SUCCESS;
49     sptr<DistributedSchedule::JsContinuationStateManagerStub> stub = CreateStub(env, info, true);
50     if (stub == nullptr || BIZTYPE_PREPARE_CONTINUE != stub->callbackData_.bizType) {
51         HILOGE("ContinueStateCallbackOn Unsupported business type: %{public}s; need: %{public}s",
52                stub == nullptr ? "" : stub->callbackData_.bizType.c_str(), BIZTYPE_PREPARE_CONTINUE.c_str());
53         napi_throw_error(env, std::to_string(ERR_DMS_WORK_ABNORMALLY).c_str(), ERR_DMS_WORK_ABNORMALLY_MSG.c_str());
54         result = FAILED;
55         napi_get_value_int32(env, ret, &result);
56         return ret;
57     }
58 
59     std::string key = std::to_string(stub->callbackData_.missionId) + stub->callbackData_.bundleName +
60             stub->callbackData_.moduleName + stub->callbackData_.abilityName;
61     auto cacheStubEntry = callbackStubs_.find(key);
62     if (cacheStubEntry == callbackStubs_.end() || cacheStubEntry->second == nullptr) {
63         callbackStubs_[key] = stub;
64     } else {
65         napi_ref oldCallbackRef = callbackStubs_[key]->callbackData_.callbackRef;
66         if (oldCallbackRef != nullptr) {
67             napi_delete_reference(env, oldCallbackRef);
68         }
69         callbackStubs_[key]->callbackData_.callbackRef = stub->callbackData_.callbackRef;
70     }
71 
72     DistributedSchedule::ContinuationStateClient client;
73     result = client.RegisterContinueStateCallback(stub);
74     HILOGI("ContinueStateCallbackOn register callback result: %{public}d", result);
75 
76     if (result != ERR_OK) {
77         napi_throw_error(env, std::to_string(ERR_DMS_WORK_ABNORMALLY).c_str(), ERR_DMS_WORK_ABNORMALLY_MSG.c_str());
78     }
79     napi_get_value_int32(env, ret, &result);
80     return ret;
81 }
82 
ContinueStateCallbackOff(napi_env env,napi_callback_info info)83 napi_value JsContinuationStateManager::ContinueStateCallbackOff(napi_env env, napi_callback_info info)
84 {
85     HILOGI("ContinueStateCallbackOff call");
86     napi_value ret = nullptr;
87     int32_t result = SUCCESS;
88     sptr<DistributedSchedule::JsContinuationStateManagerStub> stub = CreateStub(env, info, false);
89     if (stub == nullptr || BIZTYPE_PREPARE_CONTINUE != stub->callbackData_.bizType) {
90         HILOGE("ContinueStateCallbackOff Unsupported business type: %{public}s; need: %{public}s",
91                stub == nullptr ? "" : stub->callbackData_.bizType.c_str(), BIZTYPE_PREPARE_CONTINUE.c_str());
92         napi_throw_error(env, std::to_string(ERR_DMS_WORK_ABNORMALLY).c_str(), ERR_DMS_WORK_ABNORMALLY_MSG.c_str());
93         result = FAILED;
94         napi_get_value_int32(env, ret, &result);
95         return ret;
96     }
97 
98     DistributedSchedule::ContinuationStateClient client;
99     result = client.UnRegisterContinueStateCallback(stub);
100     HILOGI("ContinueStateCallbackOff unregister callback result: %{public}d", result);
101 
102     std::string key = std::to_string(stub->callbackData_.missionId) + stub->callbackData_.bundleName +
103                       stub->callbackData_.moduleName + stub->callbackData_.abilityName;
104     if (result == ERR_OK) {
105         callbackStubs_.erase(key);
106     }
107     if (stub->callbackData_.callbackRef != nullptr) {
108         int32_t state = result;
109         napi_value callback = nullptr;
110         napi_get_reference_value(env, stub->callbackData_.callbackRef, &callback);
111         napi_value undefined = nullptr;
112         napi_get_undefined(env, &undefined);
113         napi_value continueResultInfo;
114         napi_create_object(env, &continueResultInfo);
115         napi_value resultState;
116         napi_create_int32(env, state, &resultState);
117         napi_set_named_property(env, continueResultInfo, "resultState", resultState);
118         napi_value resultInfo;
119         napi_create_string_utf8(env, "", 0, &resultInfo);
120         napi_set_named_property(env, continueResultInfo, "resultInfo", resultInfo);
121         napi_value callbackResult[2] = {NULL, continueResultInfo};
122         napi_call_function(env, undefined, callback, CALLBACK_PARAMS_NUM, callbackResult, nullptr);
123     }
124 
125     if (result != ERR_OK) {
126         napi_throw_error(env, std::to_string(ERR_DMS_WORK_ABNORMALLY).c_str(), ERR_DMS_WORK_ABNORMALLY_MSG.c_str());
127     }
128     napi_get_value_int32(env, ret, &result);
129     return ret;
130 }
131 
CreateStub(napi_env env,napi_callback_info info,const bool isRegisterOn)132 sptr<DistributedSchedule::JsContinuationStateManagerStub> JsContinuationStateManager::CreateStub(
133     napi_env env, napi_callback_info info, const bool isRegisterOn)
134 {
135     // get and check all params
136     size_t argc = ARG_COUNT_THREE;
137     napi_value args[ARG_COUNT_THREE];
138     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
139     if ((argc != ARG_COUNT_THREE && isRegisterOn) || (argc < ARG_COUNT_TWO && !isRegisterOn)) {
140         HILOGE("Mandatory parameters are left unspecified");
141         napi_throw_error(env, std::to_string(PARAMETER_CHECK_FAILED).c_str(),
142             "Mandatory parameters are left unspecified.");
143         return nullptr;
144     }
145     // this.context is 2nd parameter
146     std::shared_ptr<AbilityRuntime::AbilityContext> abilityContext = nullptr;
147     GetAbilityContext(abilityContext, env, args[1]);
148     if (abilityContext == nullptr) {
149         HILOGE("get ability context failed");
150         napi_throw_error(env, std::to_string(PARAMETER_CHECK_FAILED).c_str(), "get ability context failed");
151         return nullptr;
152     }
153     std::shared_ptr<AppExecFwk::AbilityInfo> abilityInfo = abilityContext->GetAbilityInfo();
154     DistributedSchedule::JsContinuationStateManagerStub::StateCallbackData callbackData;
155     callbackData.env = env;
156     callbackData.bundleName = abilityContext->GetBundleName();
157     callbackData.moduleName = abilityInfo->moduleName;
158     callbackData.abilityName = abilityInfo->name;
159     size_t stringSize = 0;
160     std::string type;
161     napi_get_value_string_utf8(env, args[0], nullptr, 0, &stringSize);
162     napi_get_value_string_utf8(env, args[0], &type[0], stringSize + 1, &stringSize);
163     callbackData.bizType = type.c_str();
164     if (argc == ARG_COUNT_THREE) {
165         napi_valuetype valuetype;
166         napi_typeof(env, args[ARG_INDEX_4_CALLBACK_FUNC], &valuetype);
167         if (valuetype != napi_function) {
168             napi_throw_error(env, std::to_string(PARAMETER_CHECK_FAILED).c_str(),
169                 "The third parameter must be an asynchronous function");
170             return nullptr;
171         }
172         napi_ref callbackRef = nullptr;
173         napi_create_reference(env, args[ARG_INDEX_4_CALLBACK_FUNC], 1, &callbackRef);
174         callbackData.callbackRef = callbackRef;
175     }
176     abilityContext->GetMissionId(callbackData.missionId);
177     sptr<DistributedSchedule::JsContinuationStateManagerStub> stub(
178         new DistributedSchedule::JsContinuationStateManagerStub());
179     stub->callbackData_ = callbackData;
180     return stub;
181 }
182 
GetAbilityContext(std::shared_ptr<AbilityRuntime::AbilityContext> & abilityContext,napi_env env,napi_value context)183 void JsContinuationStateManager::GetAbilityContext(
184     std::shared_ptr<AbilityRuntime::AbilityContext> &abilityContext, napi_env env, napi_value context)
185 {
186     bool stageMode = false;
187     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, context, stageMode);
188     if (status != napi_ok || !stageMode) {
189         auto ability = OHOS::AbilityRuntime::GetCurrentAbility(env);
190         if (!ability) {
191             HILOGE("get ability info failed");
192             return;
193         }
194         abilityContext = ability->GetAbilityContext();
195         if (!abilityContext) {
196             HILOGE("get ability context failed");
197             return;
198         }
199     } else {
200         auto modeContext = AbilityRuntime::GetStageModeContext(env, context);
201         if (!modeContext) {
202             HILOGE("get stageMode ability info failed");
203             return;
204         }
205         abilityContext = AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(modeContext);
206         if (!abilityContext) {
207             HILOGE("get stageMode ability context failed");
208             return;
209         }
210     }
211 }
212 
MakeContinueStateCodeEnumObject(napi_env env)213 napi_value JsContinuationStateManager::MakeContinueStateCodeEnumObject(napi_env env)
214 {
215     napi_value object;
216     napi_create_object(env, &object);
217     MakeEnumItem(env, object, "SUCCESS", SUCCESS);
218     MakeEnumItem(env, object, "SYSTEM_ERROR", FAILED);
219     return object;
220 }
221 
MakeEnumItem(const napi_env & env,napi_value object,const char * name,int32_t value)222 napi_status JsContinuationStateManager::MakeEnumItem(
223     const napi_env &env, napi_value object, const char* name, int32_t value)
224 {
225     napi_value itemName;
226     napi_value itemValue;
227     napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &itemName);
228     napi_create_int32(env, value, &itemValue);
229     napi_set_property(env, object, itemName, itemValue);
230     return napi_ok;
231 }
232 
JsContinueManagerInit(napi_env env,napi_value exportObj)233 napi_value JsContinueManagerInit(napi_env env, napi_value exportObj)
234 {
235     napi_value continueStateCodeEnumObject = JsContinuationStateManager::MakeContinueStateCodeEnumObject(env);
236 
237     static napi_property_descriptor desc[] = {
238         DECLARE_NAPI_FUNCTION("on", JsContinuationStateManager::ContinueStateCallbackOn),
239         DECLARE_NAPI_FUNCTION("off", JsContinuationStateManager::ContinueStateCallbackOff),
240         DECLARE_NAPI_PROPERTY("ContinueStateCode", continueStateCodeEnumObject),
241     };
242     napi_define_properties(env, exportObj, sizeof(desc) / sizeof(desc[0]), desc);
243     return exportObj;
244 }
245 
246 static napi_module continueManagerModule = {
247     .nm_filename = "app/ability/libcontinuemanager_napi.so/continuemanager.js",
248     .nm_register_func = OHOS::DistributedSchedule::JsContinueManagerInit,
249     .nm_modname = "app.ability.continueManager",
250 };
251 
ContinuationStateManagerModuleRegister()252 extern "C" __attribute__((constructor)) void ContinuationStateManagerModuleRegister()
253 {
254     napi_module_register(&continueManagerModule);
255 }
256 } // namespace DistributedSchedule
257 } // namespace OHOS