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 "cj_request_impl.h"
17 
18 #include <string>
19 #include "constant.h"
20 #include "cj_request_task.h"
21 #include "cj_request_common.h"
22 #include "cj_request_log.h"
23 #include "cj_request_event.h"
24 #include "cj_initialize.h"
25 
26 namespace OHOS::CJSystemapi::Request {
27 using OHOS::AbilityRuntime::Context;
28 using OHOS::Request::ExceptionErrorCode;
29 using OHOS::Request::Version;
30 using OHOS::Request::E_OK_INFO;
31 using OHOS::Request::E_PERMISSION_INFO;
32 using OHOS::Request::E_PARAMETER_CHECK_INFO;
33 using OHOS::Request::E_UNSUPPORTED_INFO;
34 using OHOS::Request::E_FILE_IO_INFO;
35 using OHOS::Request::E_FILE_PATH_INFO;
36 using OHOS::Request::E_SERVICE_ERROR_INFO;
37 using OHOS::Request::E_TASK_QUEUE_INFO;
38 using OHOS::Request::E_TASK_MODE_INFO;
39 using OHOS::Request::E_TASK_NOT_FOUND_INFO;
40 using OHOS::Request::E_TASK_STATE_INFO;
41 using OHOS::Request::E_OTHER_INFO;
42 using OHOS::Request::FUNCTION_PAUSE;
43 using OHOS::Request::FUNCTION_RESUME;
44 using OHOS::Request::FUNCTION_START;
45 using OHOS::Request::FUNCTION_STOP;
46 
47 static constexpr const char *NOT_SYSTEM_APP = "permission verification failed, application which is not a system "
48                                               "application uses system API";
49 static const std::map<ExceptionErrorCode, std::string> ErrorCodeToMsg{
50     { ExceptionErrorCode::E_OK, E_OK_INFO },
51     { ExceptionErrorCode::E_PERMISSION, E_PERMISSION_INFO },
52     { ExceptionErrorCode::E_PARAMETER_CHECK, E_PARAMETER_CHECK_INFO },
53     { ExceptionErrorCode::E_UNSUPPORTED, E_UNSUPPORTED_INFO },
54     { ExceptionErrorCode::E_FILE_IO, E_FILE_IO_INFO },
55     { ExceptionErrorCode::E_FILE_PATH, E_FILE_PATH_INFO },
56     { ExceptionErrorCode::E_SERVICE_ERROR, E_SERVICE_ERROR_INFO },
57     { ExceptionErrorCode::E_TASK_QUEUE, E_TASK_QUEUE_INFO },
58     { ExceptionErrorCode::E_TASK_MODE, E_TASK_MODE_INFO },
59     { ExceptionErrorCode::E_TASK_NOT_FOUND, E_TASK_NOT_FOUND_INFO },
60     { ExceptionErrorCode::E_TASK_STATE, E_TASK_STATE_INFO },
61     { ExceptionErrorCode::E_OTHER, E_OTHER_INFO },
62     { ExceptionErrorCode::E_NOT_SYSTEM_APP, NOT_SYSTEM_APP }
63 };
64 
Convert2RetErr(ExceptionErrorCode code)65 RetError CJRequestImpl::Convert2RetErr(ExceptionErrorCode code)
66 {
67     auto iter = ErrorCodeToMsg.find(code);
68     std::string strMsg = (iter != ErrorCodeToMsg.end() ? iter->second : "");
69     return {
70         .errCode = code,
71         .errMsg = MallocCString(strMsg)
72     };
73 }
74 
Convert2RetErr(ExceptionError & err)75 RetError CJRequestImpl::Convert2RetErr(ExceptionError &err)
76 {
77     auto iter = ErrorCodeToMsg.find(err.code);
78     std::string strMsg;
79     if (err.errInfo.empty()) {
80         strMsg = (iter != ErrorCodeToMsg.end() ? iter->second : "");
81     } else {
82         strMsg = (iter != ErrorCodeToMsg.end() ? iter->second + "   " : "") + err.errInfo;
83     }
84     return {
85         .errCode = err.code,
86         .errMsg = MallocCString(strMsg)
87     };
88 }
89 
ConvertCArr2Map(const CHashStrArr * cheaders)90 std::map<std::string, std::string> CJRequestImpl::ConvertCArr2Map(const CHashStrArr *cheaders)
91 {
92     std::map<std::string, std::string> result;
93     for (int i = 0; i < cheaders->size; ++i) {
94         const CHashStrPair *cheader = &cheaders->headers[i];
95         result[cheader->key] = cheader->value;
96     }
97 
98     return result;
99 }
100 
Convert2Config(CConfig * config,Config & out)101 void CJRequestImpl::Convert2Config(CConfig *config, Config &out)
102 {
103     out.action = static_cast<OHOS::Request::Action>(config->action);
104     out.url = config->url;
105     out.version = Version::API10;  // CJ only support API10
106     out.mode = static_cast<OHOS::Request::Mode>(config->mode);
107     out.network = static_cast<OHOS::Request::Network>(config->network);
108     out.index = config->index;
109     out.begins = config->begins;
110     out.ends = config->ends;
111     out.priority = config->priority;
112     out.overwrite = config->overwrite;
113     out.metered = config->metered;
114     out.roaming = config->roaming;
115     out.retry = config->retry;
116     out.redirect = config->redirect;
117     out.gauge = config->gauge;
118     out.precise = config->precise;
119     out.title = config->title;
120     out.saveas = config->saveas;
121     out.method = config->method;
122     out.token = config->token;
123     out.description = config->description;
124     out.headers =  ConvertCArr2Map(&config->headers);
125     out.extras = ConvertCArr2Map(&config->extras);
126 }
127 
CreateTask(OHOS::AbilityRuntime::Context * context,CConfig * ffiConfig)128 RetReqData CJRequestImpl::CreateTask(OHOS::AbilityRuntime::Context* context, CConfig *ffiConfig)
129 {
130     REQUEST_HILOGD("[CJRequestImpl] CreateTask start");
131     Config config{};
132     Convert2Config(ffiConfig, config);
133     ExceptionError result = CJInitialize::ParseConfig(context, ffiConfig, config);
134     if (result.code != 0) {
135         return {
136             .err = Convert2RetErr(result)
137         };
138     }
139 
140     RetReqData ret{};
141     CJTask *task = new (std::nothrow) CJTask();
142     if (task == nullptr) {
143         REQUEST_HILOGE("[CJRequestImpl] Fail to create task.");
144         ret.err.errCode = ExceptionErrorCode::E_OTHER;
145         return ret;
146     }
147     result = task->Create(context, config);
148     if (result.code != 0) {
149         REQUEST_HILOGE("[CJRequestImpl] task create failed, ret:%{public}d.", result.code);
150         delete task;
151         return {
152             .err = Convert2RetErr(result)
153         };
154     }
155 
156     ret.taskId = MallocCString(task->taskId_);
157 
158     REQUEST_HILOGD("[CJRequestImpl] CreateTask end");
159     return ret;
160 }
161 
RemoveTask(std::string taskId)162 RetError CJRequestImpl::RemoveTask(std::string taskId)
163 {
164     RetError ret{};
165     ExceptionError result = CJTask::Remove(taskId);
166     if (result.code != ExceptionErrorCode::E_OK) {
167         return Convert2RetErr(result);
168     }
169 
170     return ret;
171 }
172 
FreeTask(std::string taskId)173 void CJRequestImpl::FreeTask(std::string taskId)
174 {
175     REQUEST_HILOGD("[CJRequestImpl] FreeTask start");
176     delete CJTask::ClearTaskMap(taskId);
177 }
178 
ProgressOn(char * event,std::string taskId,void (* callback)(CProgress progress))179 RetError CJRequestImpl::ProgressOn(char *event, std::string taskId, void (*callback)(CProgress progress))
180 {
181     REQUEST_HILOGD("[CJRequestImpl] ProgressOn start");
182     RetError ret{};
183     CJTask *task = CJTask::FindTaskById(taskId);
184     if (task == nullptr) {
185         REQUEST_HILOGE("[CJRequestImpl] Fail to find task, id:%{public}s.", taskId.c_str());
186         return Convert2RetErr(ExceptionErrorCode::E_TASK_NOT_FOUND);
187     }
188 
189     ExceptionError result = task->On(event, taskId, callback);
190     if (result.code != 0) {
191         REQUEST_HILOGE("[CJRequestImpl] task on failed, ret:%{public}d.", result.code);
192         return Convert2RetErr(result);
193     }
194 
195     return ret;
196 }
197 
ProgressOff(char * event,std::string taskId,void * callback)198 RetError CJRequestImpl::ProgressOff(char *event, std::string taskId, void *callback)
199 {
200     REQUEST_HILOGD("[CJRequestImpl] ProgressOff start");
201     RetError ret{};
202     CJTask *task = CJTask::FindTaskById(taskId);
203     if (task == nullptr) {
204         REQUEST_HILOGE("[CJRequestImpl] Fail to find task, id:%{public}s.", taskId.c_str());
205         return ret;
206     }
207 
208     ExceptionError result = task->Off(event, callback);
209     if (result.code != 0) {
210         REQUEST_HILOGE("[CJRequestImpl] task off failed, ret:%{public}d.", result.code);
211         return Convert2RetErr(result);
212     }
213 
214     return ret;
215 }
216 
TaskExec(std::string execType,std::string taskId)217 RetError CJRequestImpl::TaskExec(std::string execType, std::string taskId)
218 {
219     REQUEST_HILOGD("[CJRequestImpl] TaskExec start");
220     RetError ret{};
221     CJTask *task = CJTask::FindTaskById(taskId);
222     if (task == nullptr) {
223         REQUEST_HILOGE("[CJRequestImpl] Fail to find task, id:%{public}s.", taskId.c_str());
224         return Convert2RetErr(ExceptionErrorCode::E_TASK_NOT_FOUND);
225     }
226 
227     ExceptionErrorCode code = CJRequestEvent::Exec(execType, task);
228     if (code != ExceptionErrorCode::E_OK) {
229         return Convert2RetErr(code);
230     }
231 
232     return ret;
233 }
234 
TaskStart(std::string taskId)235 RetError CJRequestImpl::TaskStart(std::string taskId)
236 {
237     return CJRequestImpl::TaskExec(FUNCTION_START, taskId);
238 }
239 
TaskPause(std::string taskId)240 RetError CJRequestImpl::TaskPause(std::string taskId)
241 {
242     return CJRequestImpl::TaskExec(FUNCTION_PAUSE, taskId);
243 }
244 
TaskResume(std::string taskId)245 RetError CJRequestImpl::TaskResume(std::string taskId)
246 {
247     return CJRequestImpl::TaskExec(FUNCTION_RESUME, taskId);
248 }
249 
TaskStop(std::string taskId)250 RetError CJRequestImpl::TaskStop(std::string taskId)
251 {
252     return CJRequestImpl::TaskExec(FUNCTION_STOP, taskId);
253 }
254 } // namespace OHOS::CJSystemapi::Request
255