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 #ifndef NAPI_SESSION_H
17 #define NAPI_SESSION_H
18 
19 #include <condition_variable>
20 #include <map>
21 #include <memory>
22 #include <mutex>
23 #include <string>
24 #include <vector>
25 
26 #include "base_client.h"
27 #include "base_session.h"
28 #include "business_error.h"
29 #include "call_result.h"
30 #include "napi_common_define.h"
31 #include "napi_common_utils.h"
32 #include "napi_structs_base.h"
33 
34 namespace OHOS::UpdateEngine {
35 class NapiSession : public BaseSession {
36 public:
37     NapiSession(BaseClient *client, SessionParams &sessionParams, size_t argc, size_t callbackNumber);
38 
~NapiSession()39     virtual ~NapiSession() {}
40 
41     napi_value StartWork(napi_env env, const napi_value *args, DoWorkFunction worker, void *context) override;
42 
GetNapiClient()43     BaseClient* GetNapiClient() const
44     {
45         return client_;
46     }
47 
GetType()48     uint32_t GetType() const override
49     {
50         return sessionParams_.type;
51     }
52 
GetSessionId()53     uint32_t GetSessionId() const override
54     {
55         return sessionId;
56     }
57 
OnAsyncComplete(const BusinessError & businessError)58     void OnAsyncComplete(const BusinessError &businessError) final
59     {
60         std::lock_guard<std::mutex> lock(conditionVariableMutex_);
61         businessError_ = businessError;
62         asyncExecuteComplete_ = true;
63         conditionVariable_.notify_all();
64     }
65 
CompleteWork(napi_env env,napi_status status)66     virtual void CompleteWork(napi_env env, napi_status status) {}
67     virtual void ExecuteWork(napi_env env);
68     virtual napi_value StartWork(napi_env env, size_t startIndex, const napi_value *args) = 0;
69 
70     static void CompleteWork(napi_env env, napi_status status, void *data);
71     static void ExecuteWork(napi_env env, void *data);
72 
IsAsyncCompleteWork()73     bool IsAsyncCompleteWork() override
74     {
75         return false;
76     }
77 
78 protected:
79     napi_value CreateWorkerName(napi_env env) const;
80 
IsWorkExecuteSuccess()81     bool IsWorkExecuteSuccess() const
82     {
83         return workResult_ == INT_CALL_SUCCESS;
84     }
85 
GetFunctionName()86     virtual std::string GetFunctionName()
87     {
88         return "";
89     }
90 
GetFunctionPermissionName()91     virtual std::string GetFunctionPermissionName()
92     {
93         return "";
94     }
95 
BuildWorkBusinessErr(BusinessError & businessError)96     void BuildWorkBusinessErr(BusinessError &businessError)
97     {
98         std::string msg = "execute error";
99         std::string funcName;
100         std::string permissionName;
101         switch (workResult_) {
102             case INT_NOT_SYSTEM_APP:
103                 msg = "BusinessError " + std::to_string(workResult_) + NOT_SYSTEM_APP_INFO.data();
104                 break;
105             case INT_APP_NOT_GRANTED:
106                 GetSessionFuncParameter(funcName, permissionName);
107                 msg = "BusinessError " + std::to_string(workResult_) + ": Permission denied. An attempt was made to " +
108                       funcName + " forbidden by permission: " + permissionName + ".";
109                 break;
110             case INT_CALL_IPC_ERR:
111                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": IPC error.";
112                 break;
113             case INT_UN_SUPPORT:
114                 GetSessionFuncParameter(funcName, permissionName);
115                 msg = "BusinessError " + std::to_string(workResult_) + ": Capability not supported. " +
116                       "function " + funcName + " can not work correctly due to limited device capabilities.";
117                 break;
118             case INT_PARAM_ERR:
119                 msg = "BusinessError " + std::to_string(workResult_) + ": Parameter verification failed.";
120                 break;
121             case INT_CALL_FAIL:
122                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Execute fail.";
123                 break;
124             case INT_FORBIDDEN:
125                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Forbidden execution.";
126                 break;
127             case INT_DEV_UPG_INFO_ERR:
128                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Device info error.";
129                 break;
130             case INT_TIME_OUT:
131                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Execute timeout.";
132                 break;
133             case INT_DB_ERROR:
134                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": DB error.";
135                 break;
136             case INT_IO_ERROR:
137                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": IO error.";
138                 break;
139             case INT_NET_ERROR:
140                 msg = "BusinessError " + std::to_string(COMPONENT_ERR + workResult_) + ": Network error.";
141                 break;
142             default:
143                 break;
144         }
145         businessError.Build(static_cast<CallResult>(workResult_), msg);
146     }
147 
GetBusinessError(BusinessError & businessError,const NapiResult & result)148     void GetBusinessError(BusinessError &businessError, const NapiResult &result)
149     {
150         if (IsWorkExecuteSuccess()) {
151             businessError = result.businessError;
152         } else {
153             BuildWorkBusinessErr(businessError);
154         }
155     }
156 
157 protected:
158     uint32_t sessionId { 0 };
159     BaseClient *client_ = nullptr;
160     BusinessError businessError_ {};
161     SessionParams sessionParams_ {};
162     int32_t workResult_ = INT_CALL_SUCCESS;
163     size_t totalArgc_ = 0;
164     size_t callbackNumber_ = 0;
165     void* context_ {};
166     DoWorkFunction doWorker_ {};
167     std::condition_variable conditionVariable_;
168     std::mutex conditionVariableMutex_;
169     bool asyncExecuteComplete_ = false;
170 
171 private:
172     void GetSessionFuncParameter(std::string &funcName, std::string &permissionName);
173 };
174 } // namespace OHOS::UpdateEngine
175 #endif // NAPI_SESSION_H