1 /* 2 * Copyright (c) 2021 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 #ifndef UPDATE_SESSION_H 17 #define UPDATE_SESSION_H 18 19 #include <condition_variable> 20 #include <memory> 21 #include <mutex> 22 #include <string> 23 #include <vector> 24 25 #include "iupdater.h" 26 #include "iupdate_service.h" 27 #include "iupdate_session.h" 28 29 namespace OHOS { 30 namespace UpdateEngine { 31 class UpdateSession : public IUpdateSession { 32 public: 33 UpdateSession(IUpdater *client, SessionParams &sessionParams, size_t argc, size_t callbackNumber); 34 ~UpdateSession()35 virtual ~UpdateSession() {} 36 37 napi_value StartWork(napi_env env, const napi_value *args, DoWorkFunction worker, void *context) override; 38 GetUpdateClient()39 IUpdater* GetUpdateClient() const 40 { 41 return client_; 42 } 43 GetType()44 SessionType GetType() const override 45 { 46 return sessionParams_.type; 47 } 48 GetSessionId()49 uint32_t GetSessionId() const override 50 { 51 return sessionId; 52 } 53 OnAsyncComplete(const BusinessError & businessError)54 void OnAsyncComplete(const BusinessError &businessError) final 55 { 56 std::lock_guard<std::mutex> lock(conditionVariableMutex_); 57 businessError_ = businessError; 58 asyncExecuteComplete_ = true; 59 conditionVariable_.notify_all(); 60 } 61 CompleteWork(napi_env env,napi_status status)62 virtual void CompleteWork(napi_env env, napi_status status) {} 63 virtual void ExecuteWork(napi_env env); 64 virtual napi_value StartWork(napi_env env, size_t startIndex, const napi_value *args) = 0; 65 66 static void CompleteWork(napi_env env, napi_status status, void *data); 67 68 static void ExecuteWork(napi_env env, void *data); 69 IsAsyncCompleteWork()70 bool IsAsyncCompleteWork() override 71 { 72 return sessionParams_.type == SessionType::SESSION_CHECK_VERSION; 73 } 74 75 protected: 76 napi_value CreateWorkerName(napi_env env) const; 77 GetUpdateResult(UpdateResult & result)78 void GetUpdateResult(UpdateResult &result) 79 { 80 result.businessError = businessError_; 81 client_->GetUpdateResult(sessionParams_.type, result); 82 } 83 IsWorkExecuteSuccess()84 bool IsWorkExecuteSuccess() const 85 { 86 return workResult_ == INT_CALL_SUCCESS; 87 } 88 GetSessionFuncParameter(std::string & funcName,std::string & permissionName)89 void GetSessionFuncParameter(std::string &funcName, std::string &permissionName) 90 { 91 struct UpdateFuncMap { 92 SessionType type; 93 std::string func; 94 } sessionFuncMap[] = { 95 { SessionType::SESSION_CHECK_VERSION, "checkNewVersion" }, 96 { SessionType::SESSION_DOWNLOAD, "download" }, 97 { SessionType::SESSION_PAUSE_DOWNLOAD, "pauseDownload" }, 98 { SessionType::SESSION_RESUME_DOWNLOAD, "resumeDownload" }, 99 { SessionType::SESSION_UPGRADE, "upgrade" }, 100 { SessionType::SESSION_SET_POLICY, "setUpgradePolicy" }, 101 { SessionType::SESSION_GET_POLICY, "getUpgradePolicy" }, 102 { SessionType::SESSION_CLEAR_ERROR, "clearError" }, 103 { SessionType::SESSION_TERMINATE_UPGRADE, "terminateUpgrade" }, 104 { SessionType::SESSION_GET_NEW_VERSION, "getNewVersionInfo" }, 105 { SessionType::SESSION_GET_NEW_VERSION_DESCRIPTION, "getNewVersionDescription" }, 106 { SessionType::SESSION_SUBSCRIBE, "subscribe" }, 107 { SessionType::SESSION_UNSUBSCRIBE, "unsubscribe" }, 108 { SessionType::SESSION_GET_UPDATER, "getUpdater" }, 109 { SessionType::SESSION_APPLY_NEW_VERSION, "applyNewVersion" }, 110 { SessionType::SESSION_FACTORY_RESET, "factoryReset" }, 111 { SessionType::SESSION_VERIFY_PACKAGE, "verifyPackage" }, 112 { SessionType::SESSION_CANCEL_UPGRADE, "cancel" }, 113 { SessionType::SESSION_GET_CUR_VERSION, "getCurrentVersionInfo" }, 114 { SessionType::SESSION_GET_CUR_VERSION_DESCRIPTION, "getCurrentVersionDescription" }, 115 { SessionType::SESSION_GET_TASK_INFO, "getTaskInfo" }, 116 { SessionType::SESSION_REPLY_PARAM_ERROR, "replyParamError" }, 117 { SessionType::SESSION_MAX, "max" } 118 }; 119 for (auto &[type, func] : sessionFuncMap) { 120 if (type == sessionParams_.type) { 121 funcName = func; 122 break; 123 } 124 } 125 if (sessionParams_.type == SessionType::SESSION_FACTORY_RESET) { 126 permissionName = "ohos.permission.FACTORY_RESET"; 127 } else { 128 permissionName = "ohos.permission.UPDATE_SYSTEM"; 129 } 130 } 131 BuildWorkBusinessErr(BusinessError & businessError)132 void BuildWorkBusinessErr(BusinessError &businessError) 133 { 134 std::string msg = "execute error"; 135 std::string funcName = ""; 136 std::string permissionName = ""; 137 switch (workResult_) { 138 case INT_NOT_SYSTEM_APP: 139 msg = "BusinessError " + std::to_string(workResult_) + ": Caller not system app."; 140 break; 141 case INT_APP_NOT_GRANTED: 142 GetSessionFuncParameter(funcName, permissionName); 143 msg = "BusinessError " + std::to_string(workResult_) + ": Permission denied. An attempt was made to " + 144 funcName + " forbidden by permission: " + permissionName + "."; 145 break; 146 case INT_CALL_IPC_ERR: 147 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": IPC error."; 148 break; 149 case INT_UN_SUPPORT: 150 GetSessionFuncParameter(funcName, permissionName); 151 msg = "BusinessError " + std::to_string(workResult_) + ": Capability not supported. " + 152 "function " + funcName + " can not work correctly due to limited device capabilities."; 153 break; 154 case INT_PARAM_ERR: 155 msg = "param error"; 156 break; 157 case INT_CALL_FAIL: 158 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Execute fail."; 159 break; 160 case INT_FORBIDDEN: 161 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Forbidden execution."; 162 break; 163 case INT_DEV_UPG_INFO_ERR: 164 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Device info error."; 165 break; 166 case INT_TIME_OUT: 167 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Execute timeout."; 168 break; 169 case INT_DB_ERROR: 170 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": DB error."; 171 break; 172 case INT_IO_ERROR: 173 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": IO error."; 174 break; 175 case INT_NET_ERROR: 176 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Network error."; 177 break; 178 default: 179 break; 180 } 181 businessError.Build(static_cast<CallResult>(workResult_), msg); 182 } 183 GetBusinessError(BusinessError & businessError,const UpdateResult & result)184 void GetBusinessError(BusinessError &businessError, const UpdateResult &result) 185 { 186 if (IsWorkExecuteSuccess()) { 187 businessError = result.businessError; 188 } else { 189 BuildWorkBusinessErr(businessError); 190 } 191 } 192 193 uint32_t sessionId {0}; 194 IUpdater *client_ = nullptr; 195 BusinessError businessError_ {}; 196 SessionParams sessionParams_ {}; 197 int32_t workResult_ = INT_CALL_SUCCESS; 198 size_t totalArgc_ = 0; 199 size_t callbackNumber_ = 0; 200 void* context_ {}; 201 DoWorkFunction doWorker_ {}; 202 std::condition_variable conditionVariable_; 203 std::mutex conditionVariableMutex_; 204 bool asyncExecuteComplete_ = false; 205 }; 206 207 class UpdateAsyncession : public UpdateSession { 208 public: 209 UpdateAsyncession(IUpdater *client, SessionParams &sessionParams, size_t argc, size_t callbackNumber = 1) UpdateSession(client,sessionParams,argc,callbackNumber)210 : UpdateSession(client, sessionParams, argc, callbackNumber) 211 { 212 callbackRef_.resize(callbackNumber); 213 } 214 ~UpdateAsyncession()215 ~UpdateAsyncession() override 216 { 217 callbackRef_.clear(); 218 } 219 220 void CompleteWork(napi_env env, napi_status status) override; 221 napi_value StartWork(napi_env env, size_t startIndex, const napi_value *args) override; 222 void NotifyJS(napi_env env, napi_value thisVar, const UpdateResult &result) override; 223 224 private: 225 napi_async_work worker_ = nullptr; 226 std::vector<napi_ref> callbackRef_ = {0}; 227 }; 228 229 class UpdateAsyncessionNoCallback : public UpdateAsyncession { 230 public: 231 UpdateAsyncessionNoCallback( 232 IUpdater *client, SessionParams &sessionParams, size_t argc, size_t callbackNumber = 0) UpdateAsyncession(client,sessionParams,argc,callbackNumber)233 : UpdateAsyncession(client, sessionParams, argc, callbackNumber) {} 234 ~UpdateAsyncessionNoCallback()235 ~UpdateAsyncessionNoCallback() override {} 236 237 void CompleteWork(napi_env env, napi_status status) override; 238 }; 239 240 class UpdatePromiseSession : public UpdateSession { 241 public: 242 UpdatePromiseSession(IUpdater *client, SessionParams &sessionParams, size_t argc, size_t callbackNumber = 0) UpdateSession(client,sessionParams,argc,callbackNumber)243 : UpdateSession(client, sessionParams, argc, callbackNumber) {} 244 ~UpdatePromiseSession()245 ~UpdatePromiseSession() override {} 246 247 void CompleteWork(napi_env env, napi_status status) override; 248 napi_value StartWork(napi_env env, size_t startIndex, const napi_value *args) override; 249 void NotifyJS(napi_env env, napi_value thisVar, const UpdateResult &result) override; 250 251 private: 252 napi_async_work worker_ = nullptr; 253 napi_deferred deferred_ = nullptr; 254 }; 255 256 class UpdateListener : public UpdateSession { 257 public: 258 UpdateListener( 259 IUpdater *client, SessionParams &sessionParams, size_t argc, bool isOnce, size_t callbackNumber = 1) UpdateSession(client,sessionParams,argc,callbackNumber)260 : UpdateSession(client, sessionParams, argc, callbackNumber), isOnce_(isOnce) {} 261 ~UpdateListener()262 ~UpdateListener() override {} 263 264 napi_value StartWork(napi_env env, size_t startIndex, const napi_value *args) override; 265 266 void NotifyJS(napi_env env, napi_value thisVar, const UpdateResult &result) override; 267 268 void NotifyJS(napi_env env, napi_value thisVar, const EventInfo &eventInfo); 269 IsOnce()270 bool IsOnce() const 271 { 272 return isOnce_; 273 } 274 GetEventType()275 std::string GetEventType() const 276 { 277 return eventType_; 278 } 279 280 bool CheckEqual(napi_env env, napi_value handler, const std::string &type); 281 IsSubscribeEvent(const EventClassifyInfo & eventClassifyInfo)282 bool IsSubscribeEvent(const EventClassifyInfo &eventClassifyInfo) const 283 { 284 return eventClassifyInfo_.eventClassify == eventClassifyInfo.eventClassify; 285 } 286 287 bool IsSameListener(napi_env env, const EventClassifyInfo &eventClassifyInfo, napi_value handler); 288 289 void RemoveHandlerRef(napi_env env); 290 private: 291 bool isOnce_ = false; 292 std::string eventType_; 293 napi_ref handlerRef_ = nullptr; 294 std::mutex mutex_; 295 EventClassifyInfo eventClassifyInfo_; 296 }; 297 } // namespace UpdateEngine 298 } // namespace OHOS 299 #endif // UPDATE_SESSION_H 300