• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "watcher_n_exporter.h"
17 
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <memory>
22 
23 #include "../common_func.h"
24 #include "file_utils.h"
25 #include "filemgmt_libn.h"
26 #include "filemgmt_libhilog.h"
27 #include "securec.h"
28 
29 namespace OHOS::FileManagement::ModuleFileIO {
30 using namespace std;
31 using namespace OHOS::FileManagement::LibN;
32 
Constructor(napi_env env,napi_callback_info info)33 napi_value WatcherNExporter::Constructor(napi_env env, napi_callback_info info)
34 {
35     NFuncArg funcArg(env, info);
36     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
37         HILOGE("Failed to get param.");
38         NError(EINVAL).ThrowErr(env);
39         return nullptr;
40     }
41 
42     auto watcherEntity = CreateUniquePtr<WatcherEntity>();
43     if (watcherEntity == nullptr) {
44         HILOGE("Failed to request heap memory.");
45         NError(ENOMEM).ThrowErr(env);
46         return nullptr;
47     }
48     if (!NClass::SetEntityFor<WatcherEntity>(env, funcArg.GetThisVar(), move(watcherEntity))) {
49         HILOGE("Failed to set watcherEntity.");
50         NError(EIO).ThrowErr(env);
51         return nullptr;
52     }
53     return funcArg.GetThisVar();
54 }
55 
Stop(napi_env env,napi_callback_info info)56 napi_value WatcherNExporter::Stop(napi_env env, napi_callback_info info)
57 {
58     NFuncArg funcArg(env, info);
59     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
60         HILOGE("Failed to get param when stop.");
61         NError(EINVAL).ThrowErr(env);
62         return nullptr;
63     }
64 
65     auto watchEntity = NClass::GetEntityOf<WatcherEntity>(env, funcArg.GetThisVar());
66     if (!watchEntity) {
67         HILOGE("Failed to get watcherEntity when stop.");
68         NError(EINVAL).ThrowErr(env);
69         return nullptr;
70     }
71     int ret = FileWatcher::GetInstance().StopNotify(watchEntity->data_);
72     if (ret != ERRNO_NOERR) {
73         HILOGE("Failed to stopNotify errno:%{public}d", errno);
74         NError(ret).ThrowErr(env);
75         return nullptr;
76     }
77     return NVal::CreateUndefined(env).val_;
78 }
79 
Start(napi_env env,napi_callback_info info)80 napi_value WatcherNExporter::Start(napi_env env, napi_callback_info info)
81 {
82     NFuncArg funcArg(env, info);
83     if (!funcArg.InitArgs(NARG_CNT::ZERO)) {
84         HILOGE("Failed to get param when start.");
85         NError(EINVAL).ThrowErr(env);
86         return nullptr;
87     }
88 
89     auto watchEntity = NClass::GetEntityOf<WatcherEntity>(env, funcArg.GetThisVar());
90     if (!watchEntity) {
91         HILOGE("Failed to get watcherEntity when start.");
92         NError(EINVAL).ThrowErr(env);
93         return nullptr;
94     }
95 
96     int ret = FileWatcher::GetInstance().StartNotify(watchEntity->data_);
97     if (ret != ERRNO_NOERR) {
98         HILOGE("Failed to startNotify.");
99         NError(ret).ThrowErr(env);
100         return nullptr;
101     }
102 
103     auto cbExec = []() -> NError {
104         FileWatcher::GetInstance().GetNotifyEvent(WatcherCallback);
105         return NError(ERRNO_NOERR);
106     };
107 
108     auto cbCompl = [](napi_env env, NError err) -> NVal {
109         if (err) {
110             HILOGE("Failed to execute complete.");
111             return {env, err.GetNapiErr(env)};
112         }
113         return {NVal::CreateUndefined(env)};
114     };
115 
116     const string procedureName = "FileIOStartWatcher";
117     NVal thisVar(env, funcArg.GetThisVar());
118     return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbCompl).val_;
119 }
120 
WatcherCallbackComplete(WatcherNExporter::JSCallbackContext * callbackContext)121 static void WatcherCallbackComplete(WatcherNExporter::JSCallbackContext *callbackContext)
122 {
123     do {
124         if (callbackContext == nullptr) {
125             HILOGE("Failed to create context pointer");
126             break;
127         }
128         if (!callbackContext->ref_) {
129             HILOGE("Failed to get nref reference");
130             break;
131         }
132         napi_handle_scope scope = nullptr;
133         napi_status status = napi_open_handle_scope(callbackContext->env_, &scope);
134         if (status != napi_ok) {
135             HILOGE("Failed to open handle scope, status: %{public}d", status);
136             break;
137         }
138         napi_env env = callbackContext->env_;
139         napi_value jsCallback = callbackContext->ref_.Deref(env).val_;
140         NVal objn = NVal::CreateObject(env);
141         objn.AddProp("fileName", NVal::CreateUTF8String(env, callbackContext->fileName_).val_);
142         objn.AddProp("event", NVal::CreateUint32(env, callbackContext->event_).val_);
143         objn.AddProp("cookie", NVal::CreateUint32(env, callbackContext->cookie_).val_);
144         napi_value retVal = nullptr;
145         status = napi_call_function(env, nullptr, jsCallback, 1, &(objn.val_), &retVal);
146         if (status != napi_ok) {
147             HILOGE("Failed to call napi_call_function, status: %{public}d", status);
148         }
149         status = napi_close_handle_scope(callbackContext->env_, scope);
150         if (status != napi_ok) {
151             HILOGE("Failed to close handle scope, status: %{public}d", status);
152         }
153     } while (0);
154     delete callbackContext;
155 }
156 
WatcherCallback(napi_env env,NRef & callback,const std::string & fileName,const uint32_t & event,const uint32_t & cookie)157 void WatcherNExporter::WatcherCallback(napi_env env, NRef &callback, const std::string &fileName,
158                                        const uint32_t &event, const uint32_t &cookie)
159 {
160     if (!callback) {
161         HILOGE("Failed to parse watcher callback");
162         return;
163     }
164 
165     JSCallbackContext *callbackContext = new (std::nothrow) JSCallbackContext(callback);
166     if (callbackContext == nullptr) {
167         return;
168     }
169     callbackContext->env_ = env;
170     callbackContext->fileName_ = fileName;
171     callbackContext->event_ = event;
172     callbackContext->cookie_ = cookie;
173     auto task = [callbackContext] () {
174         WatcherCallbackComplete(callbackContext);
175     };
176     auto ret = napi_send_event(env, task, napi_eprio_immediate);
177     if (ret != 0) {
178         HILOGE("Failed to execute libuv work queue, ret: %{public}d", ret);
179         delete callbackContext;
180     }
181 }
182 
Export()183 bool WatcherNExporter::Export()
184 {
185     vector<napi_property_descriptor> props = {
186         NVal::DeclareNapiFunction("start", Start),
187         NVal::DeclareNapiFunction("stop", Stop),
188     };
189 
190     string className = GetClassName();
191     auto [resDefineClass, classValue] =
192         NClass::DefineClass(exports_.env_, className, WatcherNExporter::Constructor, std::move(props));
193     if (!resDefineClass) {
194         HILOGE("Failed to DefineClass");
195         NError(EIO).ThrowErr(exports_.env_);
196         return false;
197     }
198 
199     bool succ = NClass::SaveClass(exports_.env_, className, classValue);
200     if (!succ) {
201         HILOGE("Failed to SaveClass");
202         NError(EIO).ThrowErr(exports_.env_);
203         return false;
204     }
205 
206     return exports_.AddProp(className, classValue);
207 }
208 
GetClassName()209 string WatcherNExporter::GetClassName()
210 {
211     return WatcherNExporter::className_;
212 }
213 
WatcherNExporter(napi_env env,napi_value exports)214 WatcherNExporter::WatcherNExporter(napi_env env, napi_value exports) : NExporter(env, exports) {}
215 
~WatcherNExporter()216 WatcherNExporter::~WatcherNExporter() {}
217 } // namespace OHOS::FileManagement::ModuleFileIO
218