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 
16 #include "update_session.h"
17 
18 #include "node_api.h"
19 
20 #include "client_helper.h"
21 #include "napi_common_utils.h"
22 #include "update_define.h"
23 
24 using namespace std;
25 
26 namespace OHOS::UpdateEngine {
CompleteWork(napi_env env,napi_status status)27 void UpdateAsyncession::CompleteWork(napi_env env, napi_status status)
28 {
29     ENGINE_LOGI("UpdateAsyncession::CompleteWork callbackNumber_: %{public}d, %{public}d",
30         static_cast<int32_t>(callbackNumber_), sessionParams_.type);
31     UpdateResult result;
32     GetUpdateResult(result);
33     NotifyJS(env, NULL, result);
34 }
35 
GetFunctionName()36 std::string BaseUpdateSession::GetFunctionName()
37 {
38     return SessionFuncHelper::GetFuncName(sessionParams_.type);
39 }
40 
CompleteWork(napi_env env,napi_status status)41 void UpdatePromiseSession::CompleteWork(napi_env env, napi_status status)
42 {
43     UpdateResult result;
44     GetUpdateResult(result);
45     NotifyJS(env, NULL, result);
46 }
47 
GetFunctionName()48 std::string BaseMigratePromiseSession::GetFunctionName()
49 {
50     return SessionFuncHelper::GetFuncName(sessionParams_.type);
51 }
52 
StartWork(napi_env env,size_t startIndex,const napi_value * args)53 napi_value UpdateListener::StartWork(napi_env env, size_t startIndex, const napi_value *args)
54 {
55     ENGINE_LOGI("UpdateListener::StartWork");
56     PARAM_CHECK_NAPI_CALL(env, args != nullptr && totalArgc_ > startIndex, return nullptr, "Invalid para");
57 
58     if (NapiCommonUtils::IsTypeOf(env, args[0], napi_string) == ClientStatus::CLIENT_SUCCESS) {
59         int ret = NapiCommonUtils::GetString(env, args[0], eventType_);
60         PARAM_CHECK_NAPI_CALL(env, ret == napi_ok, return nullptr, "Failed to get string event type");
61     } else {
62         ClientStatus ret = ClientHelper::GetEventClassifyInfoFromArg(env, args[0], eventClassifyInfo_);
63         PARAM_CHECK_NAPI_CALL(env, ret == ClientStatus::CLIENT_SUCCESS, return nullptr, "Failed to get obj event type");
64     }
65 
66     PARAM_CHECK_NAPI_CALL(env,
67         NapiCommonUtils::IsTypeOf(env, args[startIndex], napi_function) == ClientStatus::CLIENT_SUCCESS, return nullptr,
68         "Invalid callback type");
69     ClientStatus ret = NapiCommonUtils::CreateReference(env, args[startIndex], 1, handlerRef_);
70     PARAM_CHECK_NAPI_CALL(env, ret == ClientStatus::CLIENT_SUCCESS, return nullptr, "Failed to create reference");
71     int32_t res = doWorker_(context_);
72     napi_value result;
73     napi_create_int32(env, res, &result);
74     return result;
75 }
76 
NotifyJS(napi_env env,napi_value thisVar,const UpdateResult & result)77 void UpdateListener::NotifyJS(napi_env env, napi_value thisVar, const UpdateResult &result)
78 {
79     ENGINE_LOGI("NotifyJS");
80     napi_value jsEvent;
81     napi_value handler = nullptr;
82     napi_value callResult;
83     int32_t ret = result.buildJSObject(env, jsEvent, result);
84     PARAM_CHECK_NAPI_CALL(env, ret == napi_ok, return, "Failed to build json");
85     {
86         std::lock_guard<std::mutex> lock(mutex_);
87         PARAM_CHECK_NAPI_CALL(env, handlerRef_ != nullptr, return, "handlerRef_ has beed freed");
88         napi_status status = napi_get_reference_value(env, handlerRef_, &handler);
89         PARAM_CHECK_NAPI_CALL(env, status == napi_ok && handler != nullptr, return, "Failed to get reference");
90     }
91     PARAM_CHECK_NAPI_CALL(env, handler != nullptr, return, "handlerRef_ has beed freed");
92     napi_call_function(env, thisVar, handler, 1, &jsEvent, &callResult);
93 }
94 
NotifyJS(napi_env env,napi_value thisVar,const EventInfo & eventInfo)95 void UpdateListener::NotifyJS(napi_env env, napi_value thisVar, const EventInfo &eventInfo)
96 {
97     ENGINE_LOGI("NotifyJS, eventId:0x%{public}08x", eventInfo.eventId);
98     napi_value jsEvent = nullptr;
99     ClientStatus ret = ClientHelper::BuildEventInfo(env, jsEvent, eventInfo);
100     PARAM_CHECK_NAPI_CALL(env, ret == ClientStatus::CLIENT_SUCCESS, return, "Failed to build event info");
101 
102     std::lock_guard<std::mutex> lock(mutex_);
103     PARAM_CHECK_NAPI_CALL(env, handlerRef_ != nullptr, return, "handlerRef_ has beed freed");
104     napi_value handler = nullptr;
105     napi_status status = napi_get_reference_value(env, handlerRef_, &handler);
106     PARAM_CHECK_NAPI_CALL(env, status == napi_ok && handler != nullptr, return, "Failed to get reference");
107 
108     napi_value callResult = nullptr;
109     status = napi_call_function(env, thisVar, handler, 1, &jsEvent, &callResult);
110     if (status != napi_ok) {
111         ENGINE_LOGE("NotifyJS error, napi_call_function fail");
112     }
113 }
114 
CheckEqual(napi_env env,napi_value handler,const std::string & type)115 bool UpdateListener::CheckEqual(napi_env env, napi_value handler, const std::string &type)
116 {
117     std::lock_guard<std::mutex> lock(mutex_);
118     bool isEquals = false;
119     napi_value handlerTemp = nullptr;
120     napi_status status = napi_get_reference_value(env, handlerRef_, &handlerTemp);
121     PARAM_CHECK_NAPI_CALL(env, status == napi_ok, return false, "Failed to get reference");
122     napi_strict_equals(env, handler, handlerTemp, &isEquals);
123     return isEquals && (type.compare(eventType_) == 0);
124 }
125 
IsSameListener(napi_env env,const EventClassifyInfo & eventClassifyInfo,napi_value handler)126 bool UpdateListener::IsSameListener(napi_env env, const EventClassifyInfo &eventClassifyInfo, napi_value handler)
127 {
128     if (eventClassifyInfo_.eventClassify != eventClassifyInfo.eventClassify) {
129         ENGINE_LOGI("not same listener, different event classify, 0x%{public}x, 0x%{public}x",
130             eventClassifyInfo_.eventClassify, eventClassifyInfo.eventClassify);
131         return false;
132     }
133 
134     napi_value currentHandler = nullptr;
135     napi_status status = napi_get_reference_value(env, handlerRef_, &currentHandler);
136     PARAM_CHECK_NAPI_CALL(env, status == napi_ok, return false, "Failed to get current handle");
137 
138     bool isEquals = false;
139     status = napi_strict_equals(env, handler, currentHandler, &isEquals);
140     return status == napi_ok && isEquals;
141 }
142 
RemoveHandlerRef(napi_env env)143 void UpdateListener::RemoveHandlerRef(napi_env env)
144 {
145     std::lock_guard<std::mutex> lock(mutex_);
146     ENGINE_LOGI("RemoveHandlerRef handlerRef sessionId:%{public}u", GetSessionId());
147     napi_delete_reference(env, handlerRef_);
148     handlerRef_ = nullptr;
149 }
150 
151 std::map<uint32_t, std::string> SessionFuncHelper::sessionFuncMap_ = {
152     {SessionType::SESSION_CHECK_VERSION,               "checkNewVersion"},
153     {SessionType::SESSION_DOWNLOAD,                    "download"},
154     {SessionType::SESSION_PAUSE_DOWNLOAD,              "pauseDownload"},
155     {SessionType::SESSION_RESUME_DOWNLOAD,             "resumeDownload"},
156     {SessionType::SESSION_UPGRADE,                     "upgrade"},
157     {SessionType::SESSION_SET_POLICY,                  "setUpgradePolicy"},
158     {SessionType::SESSION_GET_POLICY,                  "getUpgradePolicy"},
159     {SessionType::SESSION_CLEAR_ERROR,                 "clearError"},
160     {SessionType::SESSION_TERMINATE_UPGRADE,           "terminateUpgrade"},
161     {SessionType::SESSION_GET_NEW_VERSION,             "getNewVersionInfo"},
162     {SessionType::SESSION_GET_NEW_VERSION_DESCRIPTION, "getNewVersionDescription"},
163     {SessionType::SESSION_SUBSCRIBE,                   "subscribe"},
164     {SessionType::SESSION_UNSUBSCRIBE,                 "unsubscribe"},
165     {SessionType::SESSION_GET_UPDATER,                 "getUpdater"},
166     {SessionType::SESSION_APPLY_NEW_VERSION,           "applyNewVersion"},
167     {SessionType::SESSION_FACTORY_RESET,               "factoryReset"},
168     {SessionType::SESSION_VERIFY_PACKAGE,              "verifyPackage"},
169     {SessionType::SESSION_CANCEL_UPGRADE,              "cancel"},
170     {SessionType::SESSION_GET_CUR_VERSION,             "getCurrentVersionInfo"},
171     {SessionType::SESSION_GET_CUR_VERSION_DESCRIPTION, "getCurrentVersionDescription"},
172     {SessionType::SESSION_GET_TASK_INFO,               "getTaskInfo"},
173     {SessionType::SESSION_REPLY_PARAM_ERROR,           "replyParamError"},
174     {SessionType::SESSION_MAX,                         "max"}
175 };
176 
GetFuncName(uint32_t sessionType)177 std::string SessionFuncHelper::GetFuncName(uint32_t sessionType)
178 {
179     auto funcIter = sessionFuncMap_.find(sessionType);
180     if (funcIter == sessionFuncMap_.end()) {
181         ENGINE_LOGE("SessionFuncHelper::GetFuncName failed sessionType:%{public}d", sessionType);
182         return "";
183     }
184     return funcIter->second;
185 }
186 } // namespace OHOS::UpdateEngine