1 /*
2 * Copyright (c) 2022 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 #include "napi_app_event_watcher.h"
16
17 #include "hiappevent_base.h"
18 #include "hilog/log.h"
19 #include "napi_util.h"
20 #include "uv.h"
21
22 namespace OHOS {
23 namespace HiviewDFX {
24 namespace {
25 const HiLogLabel LABEL = { LOG_CORE, HIAPPEVENT_DOMAIN, "Napi_HiAppEvent_Watcher" };
26 constexpr size_t CALLBACK_PARAM_NUM = 3;
27
SafeDeleteWork(uv_work_t * work)28 void SafeDeleteWork(uv_work_t* work)
29 {
30 if (work != nullptr) {
31 delete work;
32 }
33 }
34 }
OnTriggerContext()35 OnTriggerContext::OnTriggerContext()
36 {
37 env = nullptr;
38 onTrigger = nullptr;
39 holder = nullptr;
40 row = 0;
41 size = 0;
42 }
43
~OnTriggerContext()44 OnTriggerContext::~OnTriggerContext()
45 {
46 if (onTrigger != nullptr) {
47 napi_delete_reference(env, onTrigger);
48 }
49 if (holder != nullptr) {
50 napi_delete_reference(env, holder);
51 }
52 }
53
NapiAppEventWatcher(const std::string & name,const std::map<std::string,unsigned int> & filters,TriggerCondition cond)54 NapiAppEventWatcher::NapiAppEventWatcher(const std::string& name, const std::map<std::string, unsigned int>& filters,
55 TriggerCondition cond) : AppEventWatcher(name, filters, cond), context_(nullptr)
56 {}
57
~NapiAppEventWatcher()58 NapiAppEventWatcher::~NapiAppEventWatcher()
59 {
60 HiLog::Debug(LABEL, "start to destroy NapiAppEventWatcher object");
61 if (context_ == nullptr) {
62 return;
63 }
64
65 uv_loop_t* loop = nullptr;
66 napi_get_uv_event_loop(context_->env, &loop);
67 uv_work_t* work = new(std::nothrow) uv_work_t();
68 work->data = (void*)context_;
69 uv_queue_work_with_qos(
70 loop,
71 work,
72 [](uv_work_t* work) {},
73 [](uv_work_t* work, int status) {
74 OnTriggerContext* context = (OnTriggerContext*)work->data;
75 HiLog::Debug(LABEL, "start to destroy OnTriggerContext object");
76 delete context;
77 SafeDeleteWork(work);
78 },
79 uv_qos_default);
80 }
81
InitHolder(const napi_env env,const napi_value holder)82 void NapiAppEventWatcher::InitHolder(const napi_env env, const napi_value holder)
83 {
84 if (context_ == nullptr) {
85 context_ = new(std::nothrow) OnTriggerContext();
86 }
87 context_->env = env;
88 context_->holder = NapiUtil::CreateReference(env, holder);
89 }
90
OnTrigger(int row,int size)91 void NapiAppEventWatcher::OnTrigger(int row, int size)
92 {
93 HiLog::Debug(LABEL, "onTrigger start");
94 if (context_ == nullptr) {
95 HiLog::Error(LABEL, "onTrigger context is null");
96 return;
97 }
98 context_->row = row;
99 context_->size = size;
100
101 uv_loop_t* loop = nullptr;
102 napi_get_uv_event_loop(context_->env, &loop);
103 uv_work_t* work = new(std::nothrow) uv_work_t();
104 work->data = (void*)context_;
105 uv_queue_work_with_qos(
106 loop,
107 work,
108 [] (uv_work_t* work) {},
109 [] (uv_work_t* work, int status) {
110 auto context = (OnTriggerContext*)work->data;
111 napi_handle_scope scope = nullptr;
112 napi_open_handle_scope(context->env, &scope);
113 if (scope == nullptr) {
114 HiLog::Error(LABEL, "failed to open handle scope");
115 SafeDeleteWork(work);
116 return;
117 }
118 napi_value callback = NapiUtil::GetReferenceValue(context->env, context->onTrigger);
119 if (callback == nullptr) {
120 HiLog::Error(LABEL, "failed to get callback from the context");
121 SafeDeleteWork(work);
122 napi_close_handle_scope(context->env, scope);
123 return;
124 }
125 napi_value argv[CALLBACK_PARAM_NUM] = {
126 NapiUtil::CreateInt32(context->env, context->row),
127 NapiUtil::CreateInt32(context->env, context->size),
128 NapiUtil::GetReferenceValue(context->env, context->holder)
129 };
130 napi_value ret = nullptr;
131 if (napi_call_function(context->env, nullptr, callback, CALLBACK_PARAM_NUM, argv, &ret) != napi_ok) {
132 HiLog::Error(LABEL, "failed to call onTrigger function");
133 }
134 napi_close_handle_scope(context->env, scope);
135 SafeDeleteWork(work);
136 },
137 uv_qos_default);
138 }
139
InitTrigger(const napi_env env,const napi_value triggerFunc)140 void NapiAppEventWatcher::InitTrigger(const napi_env env, const napi_value triggerFunc)
141 {
142 HiLog::Debug(LABEL, "start to init OnTrigger");
143 if (context_ == nullptr) {
144 context_ = new(std::nothrow) OnTriggerContext();
145 }
146 context_->env = env;
147 context_->onTrigger = NapiUtil::CreateReference(env, triggerFunc);
148 }
149 } // namespace HiviewDFX
150 } // namespace OHOS
151