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 "js_task.h"
17
18 #include <securec.h>
19 #include <sys/stat.h>
20
21 #include <chrono>
22 #include <cstring>
23 #include <filesystem>
24 #include <mutex>
25
26 #include "app_state_callback.h"
27 #include "async_call.h"
28 #include "js_initialize.h"
29 #include "legacy/request_manager.h"
30 #include "log.h"
31 #include "napi_base_context.h"
32 #include "napi_utils.h"
33 #include "request_event.h"
34 #include "request_manager.h"
35 #include "storage_acl.h"
36 #include "upload/upload_task_napiV5.h"
37
38 using namespace OHOS::StorageDaemon;
39 namespace fs = std::filesystem;
40 namespace OHOS::Request {
41 constexpr int64_t MILLISECONDS_IN_ONE_DAY = 24 * 60 * 60 * 1000;
42 std::mutex JsTask::createMutex_;
43 thread_local napi_ref JsTask::createCtor = nullptr;
44 std::mutex JsTask::requestMutex_;
45 thread_local napi_ref JsTask::requestCtor = nullptr;
46 std::mutex JsTask::requestFileMutex_;
47 thread_local napi_ref JsTask::requestFileCtor = nullptr;
48 std::mutex JsTask::getTaskCreateMutex_;
49 thread_local napi_ref JsTask::getTaskCreateCtor = nullptr;
50 std::mutex JsTask::taskMutex_;
51 std::map<std::string, JsTask *> JsTask::taskMap_;
52 bool JsTask::register_ = false;
53 std::mutex JsTask::pathMutex_;
54 std::map<std::string, int32_t> JsTask::pathMap_;
55 std::map<std::string, int32_t> JsTask::fileMap_;
56 std::mutex JsTask::taskContextMutex_;
57 std::map<std::string, std::shared_ptr<JsTask::ContextInfo>> JsTask::taskContextMap_;
58
59 napi_property_descriptor clzDes[] = {
60 DECLARE_NAPI_FUNCTION(FUNCTION_ON, RequestEvent::On),
61 DECLARE_NAPI_FUNCTION(FUNCTION_OFF, RequestEvent::Off),
62 DECLARE_NAPI_FUNCTION(FUNCTION_START, RequestEvent::Start),
63 DECLARE_NAPI_FUNCTION(FUNCTION_PAUSE, RequestEvent::Pause),
64 DECLARE_NAPI_FUNCTION(FUNCTION_RESUME, RequestEvent::Resume),
65 DECLARE_NAPI_FUNCTION(FUNCTION_STOP, RequestEvent::Stop),
66 };
67
68 napi_property_descriptor clzDesV9[] = {
69 DECLARE_NAPI_FUNCTION(FUNCTION_ON, RequestEvent::On),
70 DECLARE_NAPI_FUNCTION(FUNCTION_OFF, RequestEvent::Off),
71 DECLARE_NAPI_FUNCTION(FUNCTION_SUSPEND, RequestEvent::Pause),
72 DECLARE_NAPI_FUNCTION(FUNCTION_GET_TASK_INFO, RequestEvent::Query),
73 DECLARE_NAPI_FUNCTION(FUNCTION_GET_TASK_MIME_TYPE, RequestEvent::QueryMimeType),
74 DECLARE_NAPI_FUNCTION(FUNCTION_DELETE, RequestEvent::Remove),
75 DECLARE_NAPI_FUNCTION(FUNCTION_RESTORE, RequestEvent::Resume),
76 DECLARE_NAPI_FUNCTION(FUNCTION_PAUSE, RequestEvent::Pause),
77 DECLARE_NAPI_FUNCTION(FUNCTION_QUERY, RequestEvent::Query),
78 DECLARE_NAPI_FUNCTION(FUNCTION_QUERY_MIME_TYPE, RequestEvent::QueryMimeType),
79 DECLARE_NAPI_FUNCTION(FUNCTION_REMOVE, RequestEvent::Remove),
80 DECLARE_NAPI_FUNCTION(FUNCTION_RESUME, RequestEvent::Resume),
81 };
82
~JsTask()83 JsTask::~JsTask()
84 {
85 REQUEST_HILOGD("~JsTask()");
86 }
JsUpload(napi_env env,napi_callback_info info)87 napi_value JsTask::JsUpload(napi_env env, napi_callback_info info)
88 {
89 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
90 REQUEST_HILOGI("JsUpload seq %{public}d", seq);
91 std::shared_ptr<Upload::UploadTaskNapiV5> proxy = std::make_shared<Upload::UploadTaskNapiV5>(env);
92 if (proxy->ParseCallback(env, info)) {
93 return proxy->JsUpload(env, info);
94 }
95 proxy->SetEnv(nullptr);
96
97 return JsMain(env, info, Version::API8, seq);
98 }
99
JsDownload(napi_env env,napi_callback_info info)100 napi_value JsTask::JsDownload(napi_env env, napi_callback_info info)
101 {
102 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
103 REQUEST_HILOGI("JsDownload seq %{public}d", seq);
104 if (Legacy::RequestManager::IsLegacy(env, info)) {
105 return Legacy::RequestManager::Download(env, info);
106 }
107 return JsMain(env, info, Version::API8, seq);
108 }
109
JsRequestFile(napi_env env,napi_callback_info info)110 napi_value JsTask::JsRequestFile(napi_env env, napi_callback_info info)
111 {
112 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
113 REQUEST_HILOGI("JsRequestFile seq %{public}d", seq);
114 return JsMain(env, info, Version::API9, seq);
115 }
116
JsCreate(napi_env env,napi_callback_info info)117 napi_value JsTask::JsCreate(napi_env env, napi_callback_info info)
118 {
119 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
120 REQUEST_HILOGI("create seq %{public}d", seq);
121 return JsMain(env, info, Version::API10, seq);
122 }
123
JsMain(napi_env env,napi_callback_info info,Version version,int32_t seq)124 napi_value JsTask::JsMain(napi_env env, napi_callback_info info, Version version, int32_t seq)
125 {
126 auto context = std::make_shared<ContextInfo>();
127 context->withErrCode_ = version != Version::API8;
128 context->version_ = version;
129 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
130 if (context->version_ == Version::API10) {
131 napi_create_reference(context->env_, argv[1], 1, &(context->jsConfig));
132 }
133 napi_value ctor = GetCtor(context->env_, context->version_);
134 napi_value jsTask = nullptr;
135 napi_status status = napi_new_instance(context->env_, ctor, argc, argv, &jsTask);
136 if (jsTask == nullptr || status != napi_ok) {
137 REQUEST_HILOGE("End task create in AsyncCall input, seq: %{public}d, failed:%{public}d not "
138 "napi_ok",
139 seq, status);
140 return napi_generic_failure;
141 }
142 napi_unwrap(context->env_, jsTask, reinterpret_cast<void **>(&context->task));
143 napi_create_reference(context->env_, jsTask, 1, &(context->taskRef));
144 return napi_ok;
145 };
146 auto exec = [context, seq]() {
147 Config config = context->task->config_;
148 context->innerCode_ = CreateExec(context, seq);
149 if (context->innerCode_ == E_SERVICE_ERROR && config.version == Version::API9
150 && config.action == Action::UPLOAD) {
151 context->withErrCode_ = false;
152 }
153 };
154 auto output = [context, seq](napi_value *result) -> napi_status {
155 if (result == nullptr || context->innerCode_ != E_OK) {
156 REQUEST_HILOGE(
157 "End task create in AsyncCall output, seq: %{public}d, failed:%{public}d", seq, context->innerCode_);
158 return napi_generic_failure;
159 }
160 napi_status status = napi_get_reference_value(context->env_, context->taskRef, result);
161 context->task->SetTid(context->tid);
162 JsTask::AddTask(context);
163 napi_value config = nullptr;
164 napi_get_reference_value(context->env_, context->jsConfig, &config);
165 JsInitialize::CreatProperties(context->env_, *result, config, context->task);
166 REQUEST_HILOGI("End create seq %{public}d, tid %{public}s", seq, context->tid.c_str());
167 return status;
168 };
169 context->SetInput(input).SetOutput(output).SetExec(exec);
170 AsyncCall asyncCall(env, info, context);
171 asyncCall.SetQosLevel(napi_qos_utility);
172 return asyncCall.Call(context, "create");
173 }
174
AddTask(std::shared_ptr<ContextInfo> context)175 void JsTask::AddTask(std::shared_ptr<ContextInfo> context)
176 {
177 {
178 std::lock_guard<std::mutex> lockGuard(JsTask::taskMutex_);
179 JsTask::AddTaskMap(context->tid, context->task);
180 }
181 {
182 std::lock_guard<std::mutex> lockGuard(JsTask::taskContextMutex_);
183 JsTask::AddTaskContextMap(context->tid, context);
184 }
185 }
186
CreateExec(const std::shared_ptr<ContextInfo> & context,int32_t seq)187 int32_t JsTask::CreateExec(const std::shared_ptr<ContextInfo> &context, int32_t seq)
188 {
189 REQUEST_HILOGD("JsTask CreateExec: Action %{public}d, Mode %{public}d, seq: %{public}d",
190 context->task->config_.action, context->task->config_.mode, seq);
191 if (!RequestManager::GetInstance()->LoadRequestServer()) {
192 REQUEST_HILOGE("End create task in JsTask CreateExec, seq: %{public}d, failed: request service "
193 "not ready",
194 seq);
195 return E_SERVICE_ERROR;
196 }
197 if (context->task->config_.mode == Mode::FOREGROUND) {
198 RegisterForegroundResume();
199 }
200 int32_t ret = RequestManager::GetInstance()->Create(context->task->config_, seq, context->tid);
201 if (ret != E_OK) {
202 REQUEST_HILOGE("End create task in JsTask CreateExec, seq: %{public}d, failed: %{public}d", seq, ret);
203 return ret;
204 }
205 JsTask::AddRemoveListener(context);
206 return ret;
207 }
208
AddRemoveListener(const std::shared_ptr<ContextInfo> & context)209 void JsTask::AddRemoveListener(const std::shared_ptr<ContextInfo> &context)
210 {
211 std::string tid = context->tid;
212 context->task->listenerMutex_.lock();
213 context->task->notifyDataListenerMap_[SubscribeType::REMOVE] =
214 std::make_shared<JSNotifyDataListener>(context->env_, tid, SubscribeType::REMOVE);
215 context->task->listenerMutex_.unlock();
216 RequestManager::GetInstance()->AddListener(
217 tid, SubscribeType::REMOVE, context->task->notifyDataListenerMap_[SubscribeType::REMOVE]);
218 }
219
GetCtor(napi_env env,Version version)220 napi_value JsTask::GetCtor(napi_env env, Version version)
221 {
222 switch (version) {
223 case Version::API8:
224 return GetCtorV8(env);
225 case Version::API9:
226 return GetCtorV9(env);
227 case Version::API10:
228 return GetCtorV10(env);
229 default:
230 break;
231 }
232 return nullptr;
233 }
234
GetCtorV10(napi_env env)235 napi_value JsTask::GetCtorV10(napi_env env)
236 {
237 REQUEST_HILOGD("GetCtorV10 in");
238 std::lock_guard<std::mutex> lock(createMutex_);
239 napi_value cons;
240 if (createCtor != nullptr) {
241 NAPI_CALL(env, napi_get_reference_value(env, createCtor, &cons));
242 return cons;
243 }
244 size_t count = sizeof(clzDes) / sizeof(napi_property_descriptor);
245 return DefineClass(env, clzDes, count, Create, &createCtor);
246 }
247
GetCtorV9(napi_env env)248 napi_value JsTask::GetCtorV9(napi_env env)
249 {
250 REQUEST_HILOGD("GetCtorV9 in");
251 std::lock_guard<std::mutex> lock(requestFileMutex_);
252 napi_value cons;
253 if (requestFileCtor != nullptr) {
254 NAPI_CALL(env, napi_get_reference_value(env, requestFileCtor, &cons));
255 return cons;
256 }
257 size_t count = sizeof(clzDesV9) / sizeof(napi_property_descriptor);
258 return DefineClass(env, clzDesV9, count, RequestFile, &requestFileCtor);
259 }
260
GetCtorV8(napi_env env)261 napi_value JsTask::GetCtorV8(napi_env env)
262 {
263 REQUEST_HILOGD("GetCtorV8 in");
264 std::lock_guard<std::mutex> lock(requestMutex_);
265 napi_value cons;
266 if (requestCtor != nullptr) {
267 NAPI_CALL(env, napi_get_reference_value(env, requestCtor, &cons));
268 return cons;
269 }
270 size_t count = sizeof(clzDesV9) / sizeof(napi_property_descriptor);
271 return DefineClass(env, clzDesV9, count, RequestFileV8, &requestCtor);
272 }
273
DefineClass(napi_env env,const napi_property_descriptor * desc,size_t count,napi_callback cb,napi_ref * ctor)274 napi_value JsTask::DefineClass(
275 napi_env env, const napi_property_descriptor *desc, size_t count, napi_callback cb, napi_ref *ctor)
276 {
277 napi_value cons = nullptr;
278 napi_status status = napi_define_class(env, "Request", NAPI_AUTO_LENGTH, cb, nullptr, count, desc, &cons);
279 if (status != napi_ok) {
280 REQUEST_HILOGE("napi_define_class failed");
281 return nullptr;
282 }
283 status = napi_create_reference(env, cons, 1, ctor);
284 if (status != napi_ok) {
285 REQUEST_HILOGE("napi_create_reference failed");
286 return nullptr;
287 }
288 return cons;
289 }
290
Create(napi_env env,napi_callback_info info)291 napi_value JsTask::Create(napi_env env, napi_callback_info info)
292 {
293 REQUEST_HILOGD("Create API10");
294 return JsInitialize::Initialize(env, info, Version::API10);
295 }
296
RequestFile(napi_env env,napi_callback_info info)297 napi_value JsTask::RequestFile(napi_env env, napi_callback_info info)
298 {
299 REQUEST_HILOGD("RequestFile API9");
300 return JsInitialize::Initialize(env, info, Version::API9);
301 }
302
RequestFileV8(napi_env env,napi_callback_info info)303 napi_value JsTask::RequestFileV8(napi_env env, napi_callback_info info)
304 {
305 REQUEST_HILOGD("Request API8");
306 return JsInitialize::Initialize(env, info, Version::API8);
307 }
308
GetTaskCtor(napi_env env)309 napi_value JsTask::GetTaskCtor(napi_env env)
310 {
311 REQUEST_HILOGD("GetTaskCtor in");
312 std::lock_guard<std::mutex> lock(getTaskCreateMutex_);
313 napi_value cons;
314 if (getTaskCreateCtor != nullptr) {
315 NAPI_CALL(env, napi_get_reference_value(env, getTaskCreateCtor, &cons));
316 return cons;
317 }
318 size_t count = sizeof(clzDes) / sizeof(napi_property_descriptor);
319 return DefineClass(env, clzDes, count, GetTaskCreate, &getTaskCreateCtor);
320 }
321
GetTaskCreate(napi_env env,napi_callback_info info)322 napi_value JsTask::GetTaskCreate(napi_env env, napi_callback_info info)
323 {
324 REQUEST_HILOGD("GetTask Create");
325 return JsInitialize::Initialize(env, info, Version::API10, false);
326 }
327
GetTask(napi_env env,napi_callback_info info)328 napi_value JsTask::GetTask(napi_env env, napi_callback_info info)
329 {
330 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
331 REQUEST_HILOGI("GetTask seq %{public}d", seq);
332 auto context = std::make_shared<ContextInfo>();
333 context->withErrCode_ = true;
334 context->version_ = Version::API10;
335 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
336 ExceptionError err = ParseGetTask(context->env_, argc, argv, context);
337 if (err.code != E_OK) {
338 REQUEST_HILOGE("End get task in AsyncCall input, seq: %{public}d, failed: parse tid or token fail", seq);
339 NapiUtils::ThrowError(context->env_, err.code, err.errInfo, true);
340 return napi_invalid_arg;
341 }
342 napi_create_reference(context->env_, argv[0], 1, &(context->baseContext));
343 return napi_ok;
344 };
345 auto output = [context, seq](napi_value *result) -> napi_status {
346 if (context->innerCode_ != E_OK) {
347 REQUEST_HILOGE(
348 "End get task in AsyncCall output, seq: %{public}d, failed: %{public}d", seq, context->innerCode_);
349 return napi_generic_failure;
350 }
351 if (!GetTaskOutput(context)) {
352 REQUEST_HILOGE("End get task in AsyncCall output, seq: %{public}d, failed: get task output failed", seq);
353 return napi_generic_failure;
354 }
355 napi_status res = napi_get_reference_value(context->env_, context->taskRef, result);
356 context->task->SetTid(context->tid);
357 napi_value conf = nullptr;
358 napi_get_reference_value(context->env_, context->jsConfig, &conf);
359 JsInitialize::CreatProperties(context->env_, *result, conf, context->task);
360 REQUEST_HILOGI("End GetTask seq %{public}d", seq);
361 return res;
362 };
363 auto exec = [context]() {
364 if (!RequestManager::GetInstance()->LoadRequestServer()) {
365 context->innerCode_ = E_SERVICE_ERROR;
366 return;
367 }
368 GetTaskExecution(context);
369 };
370 context->SetInput(input).SetOutput(output).SetExec(exec);
371 AsyncCall asyncCall(env, info, context);
372 return asyncCall.Call(context, "getTask");
373 }
374
GetTaskExecution(std::shared_ptr<ContextInfo> context)375 void JsTask::GetTaskExecution(std::shared_ptr<ContextInfo> context)
376 {
377 std::string tid = context->tid;
378 REQUEST_HILOGD("Process get task, tid: %{public}s", context->tid.c_str());
379 if (taskContextMap_.find(tid) != taskContextMap_.end()) {
380 REQUEST_HILOGD("Find in taskContextMap_");
381 if (taskContextMap_[tid]->task->config_.version != Version::API10
382 || taskContextMap_[tid]->task->config_.token != context->token) {
383 context->innerCode_ = E_TASK_NOT_FOUND;
384 return;
385 }
386 context->task = taskContextMap_[tid]->task;
387 context->taskRef = taskContextMap_[tid]->taskRef;
388 context->jsConfig = taskContextMap_[tid]->jsConfig;
389 context->innerCode_ = E_OK;
390 return;
391 } else {
392 Config &config = context->config;
393 context->innerCode_ = RequestManager::GetInstance()->GetTask(tid, context->token, config);
394 if (config.action == Action::DOWNLOAD && config.files.size() != 0) {
395 config.saveas = config.files[0].uri;
396 REQUEST_HILOGD("GetTaskExecution saveas: %{public}s", config.saveas.c_str());
397 }
398 }
399 if (context->config.version != Version::API10) {
400 context->innerCode_ = E_TASK_NOT_FOUND;
401 }
402 }
403
GetTaskOutput(std::shared_ptr<ContextInfo> context)404 bool JsTask::GetTaskOutput(std::shared_ptr<ContextInfo> context)
405 {
406 std::lock_guard<std::mutex> lockGuard(JsTask::taskMutex_);
407 std::string tid = context->tid;
408
409 if (taskMap_.find(tid) != taskMap_.end()) {
410 return true;
411 }
412
413 napi_value config = NapiUtils::Convert2JSValueConfig(context->env_, context->config);
414 napi_create_reference(context->env_, config, 1, &(context->jsConfig));
415 napi_value ctor = GetTaskCtor(context->env_);
416 napi_value jsTask = nullptr;
417 napi_value baseCtx = nullptr;
418 napi_get_reference_value(context->env_, context->baseContext, &baseCtx);
419 napi_value args[2] = { baseCtx, config };
420 napi_status status = napi_new_instance(context->env_, ctor, 2, args, &jsTask);
421 if (jsTask == nullptr || status != napi_ok) {
422 REQUEST_HILOGE("Get task failed, reason: %{public}d", status);
423 return false;
424 }
425 napi_unwrap(context->env_, jsTask, reinterpret_cast<void **>(&context->task));
426 napi_create_reference(context->env_, jsTask, 1, &(context->taskRef));
427 JsTask::AddTaskMap(tid, context->task);
428 {
429 std::lock_guard<std::mutex> lockGuardContext(JsTask::taskContextMutex_);
430 JsTask::AddTaskContextMap(tid, context);
431 }
432 JsTask::AddRemoveListener(context);
433 return true;
434 }
435
ParseGetTask(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextInfo> context)436 ExceptionError JsTask::ParseGetTask(napi_env env, size_t argc, napi_value *argv, std::shared_ptr<ContextInfo> context)
437 {
438 ExceptionError err = { .code = E_OK };
439 // need at least 2 params.
440 if (argc < 2) {
441 REQUEST_HILOGE("Wrong number of arguments");
442 err.code = E_PARAMETER_CHECK;
443 err.errInfo = "Missing mandatory parameters, need at least two params, context and id";
444 return err;
445 }
446 if (NapiUtils::GetValueType(env, argv[1]) != napi_string) {
447 REQUEST_HILOGE("The parameter: tid is not of string type");
448 err.code = E_PARAMETER_CHECK;
449 err.errInfo = "Incorrect parameter type, tid is not of string type";
450 return err;
451 }
452 std::string tid = NapiUtils::Convert2String(env, argv[1]);
453 if (tid.empty()) {
454 REQUEST_HILOGE("tid is empty");
455 err.code = E_PARAMETER_CHECK;
456 err.errInfo = "Parameter verification failed, tid is empty";
457 return err;
458 }
459 // tid length <= 32
460 if (tid.size() > 32) {
461 REQUEST_HILOGE("tid invalid, %{public}s", tid.c_str());
462 err.code = E_TASK_NOT_FOUND;
463 err.errInfo = "task not found error";
464 return err;
465 }
466 context->tid = tid;
467 // handle 3rd param TOKEN
468 if (argc == 3) {
469 if (NapiUtils::GetValueType(env, argv[2]) != napi_string) { // argv[2] is the 3rd param
470 REQUEST_HILOGE("The parameter: token is not of string type");
471 err.code = E_PARAMETER_CHECK;
472 err.errInfo = "Incorrect parameter type, token is not of string type";
473 return err;
474 }
475 uint32_t bufferLen = TOKEN_MAX_BYTES + 2;
476 std::unique_ptr<char[]> token = std::make_unique<char[]>(bufferLen);
477 size_t len = 0;
478 napi_status status = napi_get_value_string_utf8(env, argv[2], token.get(), bufferLen, &len);
479 if (status != napi_ok) {
480 REQUEST_HILOGE("napi get value string utf8 failed");
481 memset_s(token.get(), bufferLen, 0, bufferLen);
482 err.code = E_PARAMETER_CHECK;
483 err.errInfo = "Parameter verification failed, get parameter token failed";
484 return err;
485 }
486 if (len < TOKEN_MIN_BYTES || len > TOKEN_MAX_BYTES) {
487 memset_s(token.get(), bufferLen, 0, bufferLen);
488 err.code = E_PARAMETER_CHECK;
489 err.errInfo = "Parameter verification failed, the length of token should between 8 and 2048 bytes";
490 return err;
491 }
492 context->token = std::string(token.get(), len);
493 memset_s(token.get(), bufferLen, 0, bufferLen);
494 }
495 return err;
496 }
497
Remove(napi_env env,napi_callback_info info)498 napi_value JsTask::Remove(napi_env env, napi_callback_info info)
499 {
500 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
501 REQUEST_HILOGI("Begin remove seq %{public}d", seq);
502 struct RemoveContext : public AsyncCall::Context {
503 std::string tid;
504 bool res = false;
505 };
506
507 auto context = std::make_shared<RemoveContext>();
508 context->withErrCode_ = true;
509 context->version_ = Version::API10;
510 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
511 ExceptionError err = ParseTid(context->env_, argc, argv, context->tid);
512 if (err.code != E_OK) {
513 REQUEST_HILOGE("End task remove in AsyncCall input, seq: %{public}d, failed: tid invalid", seq);
514 NapiUtils::ThrowError(context->env_, err.code, err.errInfo, true);
515 return napi_invalid_arg;
516 }
517 return napi_ok;
518 };
519 auto output = [context, seq](napi_value *result) -> napi_status {
520 if (context->innerCode_ != E_OK) {
521 context->res = false;
522 REQUEST_HILOGE(
523 "End task remove in AsyncCall output, seq: %{public}d, failed: %{public}d", seq, context->innerCode_);
524 return napi_generic_failure;
525 }
526 REQUEST_HILOGI("End remove seq %{public}d", seq);
527 return NapiUtils::Convert2JSValue(context->env_, context->res, *result);
528 };
529 auto exec = [context]() {
530 context->innerCode_ = RequestManager::GetInstance()->Remove(context->tid, Version::API10);
531 };
532 context->SetInput(std::move(input)).SetOutput(std::move(output)).SetExec(std::move(exec));
533 AsyncCall asyncCall(env, info, context);
534 return asyncCall.Call(context, "remove");
535 }
536
ParseTid(napi_env env,size_t argc,napi_value * argv,std::string & tid)537 ExceptionError JsTask::ParseTid(napi_env env, size_t argc, napi_value *argv, std::string &tid)
538 {
539 ExceptionError err = { .code = E_OK };
540 if (argc < 1) {
541 REQUEST_HILOGE("Wrong number of arguments");
542 err.code = E_PARAMETER_CHECK;
543 err.errInfo = "Missing mandatory parameters, missing tid";
544 return err;
545 }
546 if (NapiUtils::GetValueType(env, argv[0]) != napi_string) {
547 REQUEST_HILOGE("The first parameter is not of string type");
548 err.code = E_PARAMETER_CHECK;
549 err.errInfo = "Incorrect parameter type, tid is not of string type";
550 return err;
551 }
552 tid = NapiUtils::Convert2String(env, argv[0]);
553 if (tid.empty()) {
554 err.code = E_PARAMETER_CHECK;
555 err.errInfo = "Parameter verification failed, tid is empty";
556 return err;
557 }
558 return err;
559 }
560
Show(napi_env env,napi_callback_info info)561 napi_value JsTask::Show(napi_env env, napi_callback_info info)
562 {
563 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
564 REQUEST_HILOGI("Begin show seq %{public}d", seq);
565 auto context = std::make_shared<TouchContext>();
566 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
567 ExceptionError err = ParseTid(context->env_, argc, argv, context->tid);
568 if (err.code != E_OK) {
569 REQUEST_HILOGE("End task show in AsyncCall input, seq: %{public}d, failed: tid invalid", seq);
570 NapiUtils::ThrowError(context->env_, err.code, err.errInfo, true);
571 return napi_invalid_arg;
572 }
573 // tid length <= 32
574 if (context->tid.size() > 32) {
575 REQUEST_HILOGE("End task show in AsyncCall input, seq: %{public}d, failed: tid invalid", seq);
576 NapiUtils::ThrowError(context->env_, E_TASK_NOT_FOUND, "task not found error", true);
577 return napi_invalid_arg;
578 }
579 return napi_ok;
580 };
581 return TouchInner(env, info, std::move(input), std::move(context), seq);
582 }
583
Touch(napi_env env,napi_callback_info info)584 napi_value JsTask::Touch(napi_env env, napi_callback_info info)
585 {
586 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
587 REQUEST_HILOGI("Begin touch seq %{public}d", seq);
588 auto context = std::make_shared<TouchContext>();
589 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
590 ExceptionError err = ParseTouch(context->env_, argc, argv, context);
591 if (err.code != E_OK) {
592 REQUEST_HILOGE("End task touch in AsyncCall input, seq: %{public}d, failed: arg invalid", seq);
593 NapiUtils::ThrowError(context->env_, err.code, err.errInfo, true);
594 return napi_invalid_arg;
595 }
596 return napi_ok;
597 };
598 return TouchInner(env, info, std::move(input), std::move(context), seq);
599 }
600
TouchInner(napi_env env,napi_callback_info info,AsyncCall::Context::InputAction input,std::shared_ptr<TouchContext> context,int32_t seq)601 napi_value JsTask::TouchInner(napi_env env, napi_callback_info info, AsyncCall::Context::InputAction input,
602 std::shared_ptr<TouchContext> context, int32_t seq)
603 {
604 context->withErrCode_ = true;
605 context->version_ = Version::API10;
606 auto output = [context, seq](napi_value *result) -> napi_status {
607 if (context->innerCode_ != E_OK) {
608 REQUEST_HILOGE(
609 "End task show in AsyncCall output, seq: %{public}d, failed: %{public}d", seq, context->innerCode_);
610 return napi_generic_failure;
611 }
612 *result = NapiUtils::Convert2JSValue(context->env_, context->taskInfo);
613 REQUEST_HILOGI("End show seq %{public}d", seq);
614 return napi_ok;
615 };
616 auto exec = [context]() {
617 if (!RequestManager::GetInstance()->LoadRequestServer()) {
618 context->innerCode_ = E_SERVICE_ERROR;
619 return;
620 }
621 context->innerCode_ = RequestManager::GetInstance()->Touch(context->tid, context->token, context->taskInfo);
622 };
623 context->SetInput(std::move(input)).SetOutput(std::move(output)).SetExec(std::move(exec));
624 AsyncCall asyncCall(env, info, context);
625 return asyncCall.Call(context, "touch");
626 }
627
ParseTouch(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<TouchContext> context)628 ExceptionError JsTask::ParseTouch(napi_env env, size_t argc, napi_value *argv, std::shared_ptr<TouchContext> context)
629 {
630 ExceptionError err = { .code = E_OK };
631 // 2 means least param num.
632 if (argc < 2) {
633 REQUEST_HILOGE("Wrong number of arguments");
634 err.code = E_PARAMETER_CHECK;
635 err.errInfo = "Missing mandatory parameters, need at least two params, id and token";
636 return err;
637 }
638 if (NapiUtils::GetValueType(env, argv[0]) != napi_string || NapiUtils::GetValueType(env, argv[1]) != napi_string) {
639 REQUEST_HILOGE("The parameter: tid is not of string type");
640 err.code = E_PARAMETER_CHECK;
641 err.errInfo = "Incorrect parameter type, tid is not of string type";
642 return err;
643 }
644 context->tid = NapiUtils::Convert2String(env, argv[0]);
645 if (context->tid.empty()) {
646 REQUEST_HILOGE("tid is empty");
647 err.code = E_PARAMETER_CHECK;
648 err.errInfo = "Parameter verification failed, tid is empty";
649 return err;
650 }
651 // tid length <= 32
652 if (context->tid.size() > 32) {
653 REQUEST_HILOGE("tid invalid, %{public}s", context->tid.c_str());
654 err.code = E_TASK_NOT_FOUND;
655 err.errInfo = "task not found error";
656 return err;
657 }
658 uint32_t bufferLen = TOKEN_MAX_BYTES + 2;
659 char *token = new char[bufferLen];
660 size_t len = 0;
661 napi_status status = napi_get_value_string_utf8(env, argv[1], token, bufferLen, &len);
662 if (status != napi_ok) {
663 REQUEST_HILOGE("napi get value string utf8 failed");
664 memset_s(token, bufferLen, 0, bufferLen);
665 delete[] token;
666 err.code = E_PARAMETER_CHECK;
667 err.errInfo = "Parameter verification failed, get token failed";
668 return err;
669 }
670 if (len < TOKEN_MIN_BYTES || len > TOKEN_MAX_BYTES) {
671 memset_s(token, bufferLen, 0, bufferLen);
672 delete[] token;
673 err.code = E_PARAMETER_CHECK;
674 err.errInfo = "Parameter verification failed, the length of token should between 8 and 2048 bytes";
675 return err;
676 }
677 context->token = std::string(token, len);
678 memset_s(token, bufferLen, 0, bufferLen);
679 delete[] token;
680 return err;
681 }
682
ParseSearch(napi_env env,size_t argc,napi_value * argv,Filter & filter)683 ExceptionError JsTask::ParseSearch(napi_env env, size_t argc, napi_value *argv, Filter &filter)
684 {
685 ExceptionError err = { .code = E_OK };
686 using namespace std::chrono;
687 filter.bundle = "*";
688 filter.before = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
689 filter.after = filter.before - MILLISECONDS_IN_ONE_DAY;
690 if (argc < 1) {
691 return err;
692 }
693 napi_valuetype valueType = NapiUtils::GetValueType(env, argv[0]);
694 if (valueType == napi_null || valueType == napi_undefined) {
695 return err;
696 }
697 if (valueType != napi_object) {
698 REQUEST_HILOGE("The parameter: filter is not of object type");
699 err.code = E_PARAMETER_CHECK;
700 err.errInfo = "Incorrect parameter type, filter is not of object type";
701 return err;
702 }
703 filter.bundle = ParseBundle(env, argv[0]);
704 filter.before = ParseBefore(env, argv[0]);
705 filter.after = ParseAfter(env, argv[0], filter.before);
706 if (filter.before < filter.after) {
707 REQUEST_HILOGE("before is small than after");
708 err.code = E_PARAMETER_CHECK;
709 err.errInfo = "Parameter verification failed, filter before is small than after";
710 return err;
711 }
712 filter.state = ParseState(env, argv[0]);
713 filter.action = ParseAction(env, argv[0]);
714 filter.mode = ParseMode(env, argv[0]);
715 return err;
716 }
717
ParseBundle(napi_env env,napi_value value)718 std::string JsTask::ParseBundle(napi_env env, napi_value value)
719 {
720 if (!NapiUtils::HasNamedProperty(env, value, "bundle")) {
721 return "*";
722 }
723 napi_value value1 = NapiUtils::GetNamedProperty(env, value, "bundle");
724 if (NapiUtils::GetValueType(env, value1) != napi_string) {
725 return "*";
726 }
727 return NapiUtils::Convert2String(env, value1);
728 }
729
ParseState(napi_env env,napi_value value)730 State JsTask::ParseState(napi_env env, napi_value value)
731 {
732 if (!NapiUtils::HasNamedProperty(env, value, "state")) {
733 return State::ANY;
734 }
735 napi_value value1 = NapiUtils::GetNamedProperty(env, value, "state");
736 if (NapiUtils::GetValueType(env, value1) != napi_number) {
737 return State::ANY;
738 }
739 return static_cast<State>(NapiUtils::Convert2Uint32(env, value1));
740 }
741
ParseAction(napi_env env,napi_value value)742 Action JsTask::ParseAction(napi_env env, napi_value value)
743 {
744 if (!NapiUtils::HasNamedProperty(env, value, "action")) {
745 return Action::ANY;
746 }
747 napi_value value1 = NapiUtils::GetNamedProperty(env, value, "action");
748 if (NapiUtils::GetValueType(env, value1) != napi_number) {
749 return Action::ANY;
750 }
751 return static_cast<Action>(NapiUtils::Convert2Uint32(env, value1));
752 }
753
ParseMode(napi_env env,napi_value value)754 Mode JsTask::ParseMode(napi_env env, napi_value value)
755 {
756 if (!NapiUtils::HasNamedProperty(env, value, "mode")) {
757 return Mode::ANY;
758 }
759 napi_value value1 = NapiUtils::GetNamedProperty(env, value, "mode");
760 if (NapiUtils::GetValueType(env, value1) != napi_number) {
761 return Mode::ANY;
762 }
763 return static_cast<Mode>(NapiUtils::Convert2Uint32(env, value1));
764 }
765
ParseBefore(napi_env env,napi_value value)766 int64_t JsTask::ParseBefore(napi_env env, napi_value value)
767 {
768 using namespace std::chrono;
769 int64_t now = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
770 if (!NapiUtils::HasNamedProperty(env, value, "before")) {
771 return now;
772 }
773 napi_value value1 = NapiUtils::GetNamedProperty(env, value, "before");
774 if (NapiUtils::GetValueType(env, value1) != napi_number) {
775 return now;
776 }
777 int64_t ret = 0;
778 NAPI_CALL_BASE(env, napi_get_value_int64(env, value1, &ret), now);
779 return ret;
780 }
781
ParseAfter(napi_env env,napi_value value,int64_t before)782 int64_t JsTask::ParseAfter(napi_env env, napi_value value, int64_t before)
783 {
784 int64_t defaultValue = before - MILLISECONDS_IN_ONE_DAY;
785 if (!NapiUtils::HasNamedProperty(env, value, "after")) {
786 return defaultValue;
787 }
788 napi_value value1 = NapiUtils::GetNamedProperty(env, value, "after");
789 if (NapiUtils::GetValueType(env, value1) != napi_number) {
790 return defaultValue;
791 }
792 int64_t ret = 0;
793 NAPI_CALL_BASE(env, napi_get_value_int64(env, value1, &ret), defaultValue);
794 return ret;
795 }
796
Search(napi_env env,napi_callback_info info)797 napi_value JsTask::Search(napi_env env, napi_callback_info info)
798 {
799 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
800 REQUEST_HILOGI("Begin search seq %{public}d", seq);
801 struct SearchContext : public AsyncCall::Context {
802 Filter filter;
803 std::vector<std::string> tids;
804 };
805
806 auto context = std::make_shared<SearchContext>();
807 context->withErrCode_ = true;
808 context->version_ = Version::API10;
809 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
810 ExceptionError err = ParseSearch(context->env_, argc, argv, context->filter);
811 if (err.code != E_OK) {
812 REQUEST_HILOGE("End task search in AsyncCall input, seq: %{public}d, failed: arg invalid", seq);
813 NapiUtils::ThrowError(context->env_, err.code, err.errInfo, true);
814 return napi_invalid_arg;
815 }
816 return napi_ok;
817 };
818 auto output = [context, seq](napi_value *result) -> napi_status {
819 if (context->innerCode_ != E_OK) {
820 REQUEST_HILOGE(
821 "End task search in AsyncCall output, seq: %{public}d, failed: %{public}d", seq, context->innerCode_);
822 return napi_generic_failure;
823 }
824 *result = NapiUtils::Convert2JSValue(context->env_, context->tids);
825 REQUEST_HILOGI("End search seq %{public}d", seq);
826 return napi_ok;
827 };
828 auto exec = [context]() {
829 if (!RequestManager::GetInstance()->LoadRequestServer()) {
830 context->innerCode_ = E_SERVICE_ERROR;
831 return;
832 }
833 context->innerCode_ = RequestManager::GetInstance()->Search(context->filter, context->tids);
834 };
835 context->SetInput(std::move(input)).SetOutput(std::move(output)).SetExec(std::move(exec));
836 AsyncCall asyncCall(env, info, context);
837 return asyncCall.Call(context, "search");
838 }
839
Query(napi_env env,napi_callback_info info)840 napi_value JsTask::Query(napi_env env, napi_callback_info info)
841 {
842 int32_t seq = RequestManager::GetInstance()->GetNextSeq();
843 REQUEST_HILOGI("Begin query seq %{public}d", seq);
844 struct QueryContext : public AsyncCall::Context {
845 std::string tid;
846 TaskInfo taskInfo;
847 };
848
849 auto context = std::make_shared<QueryContext>();
850 context->withErrCode_ = true;
851 context->version_ = Version::API10;
852 auto input = [context, seq](size_t argc, napi_value *argv, napi_value self) -> napi_status {
853 ExceptionError err = ParseTid(context->env_, argc, argv, context->tid);
854 if (err.code != E_OK) {
855 REQUEST_HILOGE("End task query in AsyncCall input, seq: %{public}d, failed: tid invalid", seq);
856 NapiUtils::ThrowError(context->env_, err.code, err.errInfo, true);
857 return napi_invalid_arg;
858 }
859 return napi_ok;
860 };
861 auto output = [context, seq](napi_value *result) -> napi_status {
862 if (context->innerCode_ != E_OK) {
863 REQUEST_HILOGE(
864 "End task query in AsyncCall output, seq: %{public}d, failed: %{public}d", seq, context->innerCode_);
865 return napi_generic_failure;
866 }
867 context->taskInfo.withSystem = true;
868 *result = NapiUtils::Convert2JSValue(context->env_, context->taskInfo);
869 REQUEST_HILOGI("End query seq %{public}d", seq);
870 return napi_ok;
871 };
872 auto exec = [context]() {
873 if (!RequestManager::GetInstance()->LoadRequestServer()) {
874 context->innerCode_ = E_SERVICE_ERROR;
875 return;
876 }
877 context->innerCode_ = RequestManager::GetInstance()->Query(context->tid, context->taskInfo);
878 };
879 context->SetInput(std::move(input)).SetOutput(std::move(output)).SetExec(std::move(exec));
880 AsyncCall asyncCall(env, info, context);
881 return asyncCall.Call(context, "query");
882 }
883
GetTid()884 std::string JsTask::GetTid()
885 {
886 return tid_;
887 }
888
SetTid(std::string & tid)889 void JsTask::SetTid(std::string &tid)
890 {
891 tid_ = tid;
892 }
893
AddTaskMap(const std::string & key,JsTask * task)894 void JsTask::AddTaskMap(const std::string &key, JsTask *task)
895 {
896 JsTask::taskMap_[key] = task;
897
898 if (!JsTask::taskMap_.empty()) {
899 JsTask::SubscribeSA();
900 }
901 }
902
AddTaskContextMap(const std::string & key,std::shared_ptr<ContextInfo> context)903 void JsTask::AddTaskContextMap(const std::string &key, std::shared_ptr<ContextInfo> context)
904 {
905 JsTask::taskContextMap_[key] = context;
906 }
907
SubscribeSA()908 void JsTask::SubscribeSA()
909 {
910 REQUEST_HILOGD("SubscribeSA in");
911 if (!RequestManager::GetInstance()->SubscribeSA()) {
912 REQUEST_HILOGE("SubscribeSA Failed");
913 }
914 }
915
UnsubscribeSA()916 void JsTask::UnsubscribeSA()
917 {
918 REQUEST_HILOGD("UnsubscribeSA in");
919 if (!RequestManager::GetInstance()->UnsubscribeSA()) {
920 REQUEST_HILOGE("UnsubscribeSA Failed");
921 }
922 }
923
ReloadListener()924 void JsTask::ReloadListener()
925 {
926 REQUEST_HILOGD("ReloadListener in");
927 // collect all tids first to reduce lock holding time
928 std::vector<std::string> tids;
929 {
930 std::lock_guard<std::mutex> lockGuard(JsTask::taskMutex_);
931 for (const auto &it : taskMap_) {
932 tids.push_back(it.first);
933 }
934 }
935 for (const auto &it : tids) {
936 REQUEST_HILOGD("ReloadListener tid: %{public}s", it.c_str());
937 RequestManager::GetInstance()->Subscribe(it);
938 }
939 }
940
ClearTaskMap(const std::string & key)941 void JsTask::ClearTaskMap(const std::string &key)
942 {
943 std::lock_guard<std::mutex> lockGuard(JsTask::taskMutex_);
944 auto it = taskMap_.find(key);
945 if (it != taskMap_.end()) {
946 taskMap_.erase(it);
947 }
948 if (taskMap_.empty()) {
949 JsTask::UnsubscribeSA();
950 }
951 }
952
SetDirsPermission(std::vector<std::string> & dirs)953 bool JsTask::SetDirsPermission(std::vector<std::string> &dirs)
954 {
955 if (dirs.empty()) {
956 return true;
957 }
958 std::string newPath = "/data/storage/el2/base/.ohos/.request/.certs";
959 std::vector<std::string> dirElems;
960 JsInitialize::StringSplit(newPath, '/', dirElems);
961 if (!JsInitialize::CreateDirs(dirElems)) {
962 REQUEST_HILOGE("CreateDirs Err: %{public}s", newPath.c_str());
963 return false;
964 }
965
966 for (const auto &folderPath : dirs) {
967 fs::path folder = folderPath;
968 if (!(fs::exists(folder) && fs::is_directory(folder))) {
969 return false;
970 }
971 for (const auto &entry : fs::directory_iterator(folder)) {
972 fs::path path = entry.path();
973 std::string existfilePath = folder.string() + "/" + path.filename().string();
974 std::string newfilePath = newPath + "/" + path.filename().string();
975 if (!fs::exists(newfilePath)) {
976 fs::copy(existfilePath, newfilePath);
977 }
978 if (chmod(newfilePath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) {
979 REQUEST_HILOGD("File add OTH access Failed.");
980 }
981 REQUEST_HILOGD("current filePath is %{public}s", newfilePath.c_str());
982 if (!JsTask::SetPathPermission(newfilePath)) {
983 REQUEST_HILOGE("Set path permission fail.");
984 return false;
985 }
986 }
987 }
988 if (!dirs.empty()) {
989 dirs.clear();
990 dirs.push_back(newPath);
991 }
992 return true;
993 }
994
SetPathPermission(const std::string & filepath)995 bool JsTask::SetPathPermission(const std::string &filepath)
996 {
997 std::string baseDir;
998 if (!JsInitialize::CheckBelongAppBaseDir(filepath, baseDir)) {
999 return false;
1000 }
1001
1002 AddPathMap(filepath, baseDir);
1003 {
1004 std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
1005 for (auto it : pathMap_) {
1006 if (it.second <= 0) {
1007 continue;
1008 }
1009 if (AclSetAccess(it.first, SA_PERMISSION_X) != ACL_SUCC) {
1010 REQUEST_HILOGE("AclSetAccess Parent Dir Failed: %{public}s", it.first.c_str());
1011 }
1012 }
1013 }
1014
1015 if (AclSetAccess(filepath, SA_PERMISSION_RWX) != ACL_SUCC) {
1016 REQUEST_HILOGE("AclSetAccess Child Dir Failed: %{public}s", filepath.c_str());
1017 return false;
1018 }
1019 return true;
1020 }
1021
AddPathMap(const std::string & filepath,const std::string & baseDir)1022 void JsTask::AddPathMap(const std::string &filepath, const std::string &baseDir)
1023 {
1024 {
1025 std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
1026 auto it = fileMap_.find(filepath);
1027 if (it == fileMap_.end()) {
1028 fileMap_[filepath] = 1;
1029 } else {
1030 fileMap_[filepath] += 1;
1031 }
1032 }
1033
1034 std::string childDir(filepath);
1035 std::string parentDir;
1036 while (childDir.length() > baseDir.length()) {
1037 parentDir = childDir.substr(0, childDir.rfind("/"));
1038 std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
1039 auto it = pathMap_.find(parentDir);
1040 if (it == pathMap_.end()) {
1041 pathMap_[parentDir] = 1;
1042 } else {
1043 pathMap_[parentDir] += 1;
1044 }
1045 childDir = parentDir;
1046 }
1047 }
1048
ResetDirAccess(const std::string & filepath)1049 void JsTask::ResetDirAccess(const std::string &filepath)
1050 {
1051 int ret = AclSetAccess(filepath, SA_PERMISSION_CLEAN);
1052 if (ret != ACL_SUCC) {
1053 REQUEST_HILOGD("AclSetAccess Reset Dir Failed: %{public}s", filepath.c_str());
1054 }
1055 }
1056
RemovePathMap(const std::string & filepath)1057 void JsTask::RemovePathMap(const std::string &filepath)
1058 {
1059 std::string baseDir;
1060 if (!JsInitialize::CheckBelongAppBaseDir(filepath, baseDir)) {
1061 return;
1062 }
1063
1064 {
1065 std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
1066 auto it = fileMap_.find(filepath);
1067 if (it != fileMap_.end()) {
1068 if (fileMap_[filepath] <= 1) {
1069 fileMap_.erase(filepath);
1070 if (chmod(filepath.c_str(), S_IRUSR | S_IWUSR | S_IRGRP) != 0) {
1071 REQUEST_HILOGE("File remove OTH access Failed: %{public}s", filepath.c_str());
1072 }
1073 } else {
1074 fileMap_[filepath] -= 1;
1075 }
1076 } else {
1077 return;
1078 }
1079 }
1080
1081 std::string childDir(filepath);
1082 std::string parentDir;
1083 while (childDir.length() > baseDir.length()) {
1084 parentDir = childDir.substr(0, childDir.rfind("/"));
1085 std::lock_guard<std::mutex> lockGuard(JsTask::pathMutex_);
1086 auto it = pathMap_.find(parentDir);
1087 if (it != pathMap_.end()) {
1088 if (pathMap_[parentDir] <= 1) {
1089 pathMap_.erase(parentDir);
1090 ResetDirAccess(parentDir);
1091 } else {
1092 pathMap_[parentDir] -= 1;
1093 }
1094 }
1095 childDir = parentDir;
1096 }
1097 }
1098
RemoveDirsPermission(const std::vector<std::string> & dirs)1099 void JsTask::RemoveDirsPermission(const std::vector<std::string> &dirs)
1100 {
1101 for (const auto &folderPath : dirs) {
1102 fs::path folder = folderPath;
1103 for (const auto &entry : fs::directory_iterator(folder)) {
1104 fs::path path = entry.path();
1105 std::string filePath = folder.string() + "/" + path.filename().string();
1106 RemovePathMap(filePath);
1107 }
1108 }
1109 }
1110
ClearTaskTemp(const std::string & tid,bool isRmFiles,bool isRmAcls,bool isRmCertsAcls)1111 void JsTask::ClearTaskTemp(const std::string &tid, bool isRmFiles, bool isRmAcls, bool isRmCertsAcls)
1112 {
1113 std::lock_guard<std::mutex> lockGuard(JsTask::taskContextMutex_);
1114 auto it = taskContextMap_.find(tid);
1115 if (it == taskContextMap_.end()) {
1116 REQUEST_HILOGD("Clear task tmp files, not in ContextMap");
1117 return;
1118 }
1119 auto context = it->second;
1120
1121 if (isRmFiles) {
1122 auto bodyFileNames = context->task->config_.bodyFileNames;
1123 for (auto &filePath : bodyFileNames) {
1124 std::error_code err;
1125 if (!std::filesystem::exists(filePath, err)) {
1126 continue;
1127 }
1128 err.clear();
1129 RemovePathMap(filePath);
1130 NapiUtils::RemoveFile(filePath);
1131 }
1132 }
1133 if (isRmAcls) {
1134 // Reset Acl permission
1135 for (auto &file : context->task->config_.files) {
1136 RemovePathMap(file.uri);
1137 }
1138 context->task->isGetPermission = false;
1139 }
1140 if (isRmCertsAcls) {
1141 RemoveDirsPermission(context->task->config_.certsPath);
1142 }
1143 }
1144
RemoveTaskContext(const std::string & tid)1145 void JsTask::RemoveTaskContext(const std::string &tid)
1146 {
1147 std::lock_guard<std::mutex> lockGuard(JsTask::taskContextMutex_);
1148 auto it = taskContextMap_.find(tid);
1149 if (it == taskContextMap_.end()) {
1150 REQUEST_HILOGD("Clear task tmp files, not in ContextMap");
1151 return;
1152 }
1153 auto context = it->second;
1154
1155 auto map = context->task->notifyDataListenerMap_;
1156 for (auto i = map.begin(); i != map.end();i++) {
1157 i->second->DeleteAllListenerRef();
1158 }
1159 map.clear();
1160 taskContextMap_.erase(it);
1161 UnrefTaskContextMap(context);
1162 }
1163
UnrefTaskContextMap(std::shared_ptr<ContextInfo> context)1164 void JsTask::UnrefTaskContextMap(std::shared_ptr<ContextInfo> context)
1165 {
1166 ContextCallbackData *data = new ContextCallbackData();
1167 if (data == nullptr) {
1168 return;
1169 }
1170 data->context = context;
1171 auto callback = [data]() {
1172 if (data == nullptr) {
1173 // Ensure that the `work` is not nullptr.
1174 return;
1175 }
1176 napi_handle_scope scope = nullptr;
1177 napi_open_handle_scope(data->context->env_, &scope);
1178 if (scope == nullptr) {
1179 delete data;
1180 return;
1181 }
1182 u_int32_t taskRefCount = 0;
1183 napi_reference_unref(data->context->env_, data->context->taskRef, &taskRefCount);
1184 REQUEST_HILOGD("Unref task ref, count is %{public}d", taskRefCount);
1185 if (taskRefCount == 0) {
1186 napi_delete_reference(data->context->env_, data->context->taskRef);
1187 }
1188 if (data->context->version_ == Version::API10) {
1189 u_int32_t configRefCount = 0;
1190 napi_reference_unref(data->context->env_, data->context->jsConfig, &configRefCount);
1191 REQUEST_HILOGI("Unref task config ref, count is %{public}d", configRefCount);
1192 if (configRefCount == 0) {
1193 napi_delete_reference(data->context->env_, data->context->jsConfig);
1194 }
1195 }
1196 napi_close_handle_scope(data->context->env_, scope);
1197 delete data;
1198 return;
1199 };
1200
1201 int32_t ret = napi_send_event(data->context->env_, callback, napi_eprio_high);
1202 if (ret != napi_ok) {
1203 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
1204 delete data;
1205 }
1206
1207 return;
1208 }
1209
Equals(napi_env env,napi_value value,napi_ref copy)1210 bool JsTask::Equals(napi_env env, napi_value value, napi_ref copy)
1211 {
1212 if (copy == nullptr) {
1213 return (value == nullptr);
1214 }
1215
1216 napi_value copyValue = nullptr;
1217 napi_get_reference_value(env, copy, ©Value);
1218
1219 bool isEquals = false;
1220 napi_strict_equals(env, value, copyValue, &isEquals);
1221 return isEquals;
1222 }
1223
RegisterForegroundResume()1224 void JsTask::RegisterForegroundResume()
1225 {
1226 if (register_) {
1227 return;
1228 }
1229 REQUEST_HILOGI("Process register foreground resume callback");
1230 register_ = true;
1231 auto context = AbilityRuntime::ApplicationContext::GetInstance();
1232 if (context == nullptr) {
1233 REQUEST_HILOGE("End register foreground resume callback, failed: Get ApplicationContext failed");
1234 return;
1235 }
1236 context->RegisterAbilityLifecycleCallback(std::make_shared<AppStateCallback>());
1237 REQUEST_HILOGI("End register foreground resume callback successfully");
1238 }
1239 } // namespace OHOS::Request