1 /*
2 * Copyright (c) 2021 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 "file_picker_exporter.h"
16
17 #include <cstdio>
18 #include <cstdlib>
19 #include <string>
20 #include <vector>
21
22 #include "../common/ability_helper.h"
23 #include "../common/common_func.h"
24 #include "../common/napi/n_class.h"
25 #include "../common/napi/n_func_arg.h"
26 #include "../common/napi/n_val.h"
27 #include "../common/uni_error.h"
28 #include "file_info.h"
29 #include "root_info.h"
30 #include "storage_ability.h"
31 #include "uri.h"
32
33 using Uri = OHOS::Uri;
34 using namespace std;
35 namespace OHOS {
36 namespace DistributedFS {
37 namespace ModuleFPExpoter {
38 enum COMMON_NUM {
39 ZERO = 0,
40 ONE = 1,
41 TWO = 2,
42 THREE = 3,
43 };
44
45 enum ERROR_CODE {
46 SUCCESS_CODE = 200,
47 OTHER_ARGUMENT_ERROR = 202,
48 FILE_IO_ERROR = 300,
49 FILE_PATH_ERROR = 301,
50 URI_PARAMER_ERROR = 302,
51 };
52
CallBackSuccess(napi_env env,napi_ref successFuncRef,int32_t count,napi_value obj)53 void CallBackSuccess(napi_env env, napi_ref successFuncRef, int32_t count, napi_value obj)
54 {
55 napi_value results = nullptr;
56 napi_value successFunc = nullptr;
57 napi_value global = nullptr;
58 napi_get_global(env, &global);
59 napi_get_reference_value(env, successFuncRef, &successFunc);
60 if (successFunc == nullptr) {
61 return;
62 }
63 napi_call_function(env, global, successFunc, count, &obj, &results);
64 }
65
CallBackError(napi_env env,napi_ref failFuncRef,string errorProp,int errorCode)66 void CallBackError(napi_env env, napi_ref failFuncRef, string errorProp, int errorCode)
67 {
68 napi_value argvFail[2] = { 0 };
69 napi_value results = nullptr;
70 napi_value failFunc = nullptr;
71 napi_value global = nullptr;
72 napi_get_global(env, &global);
73 argvFail[0] = NVal::CreateUTF8String(env, errorProp).val_;
74 argvFail[1] = NVal::CreateInt32(env, errorCode).val_;
75 napi_get_reference_value(env, failFuncRef, &failFunc);
76 if (failFunc == nullptr) {
77 return;
78 }
79 napi_call_function(env, global, failFunc, COMMON_NUM::TWO, argvFail, &results);
80 }
81
CallComplete(napi_env env,napi_ref completeFuncRef)82 void CallComplete(napi_env env, napi_ref completeFuncRef)
83 {
84 napi_value completeFunc = nullptr;
85 napi_value results = nullptr;
86 napi_value global = nullptr;
87 napi_get_global(env, &global);
88 napi_get_reference_value(env, completeFuncRef, &completeFunc);
89 if (completeFunc == nullptr) {
90 return;
91 }
92 napi_call_function(env, global, completeFunc, COMMON_NUM::ZERO, nullptr, &results);
93 }
94
SaveFileExec(napi_env env,void * data)95 void SaveFileExec(napi_env env, void *data)
96 {
97 auto *asyncInfo = (SaveFileAsyncInfo *)data;
98 unique_ptr<FileManager::StorageAbility> point;
99 vector<FileManager::SaveFileInfo> result;
100 Uri uriObj(asyncInfo->dstPath);
101 asyncInfo->err = point->SaveFiles(uriObj, asyncInfo->srcPath, result);
102 asyncInfo->saveFileList.assign(result.begin(), result.end());
103 }
104
SaveFileComp(napi_env env,napi_status status,void * data)105 void SaveFileComp(napi_env env, napi_status status, void *data)
106 {
107 auto *asyncInfo = (SaveFileAsyncInfo *)data;
108 if (asyncInfo->err == ERROR_CODE::SUCCESS_CODE) {
109 napi_value saveListNapi;
110 napi_create_array(env, &saveListNapi);
111 int32_t i = 0;
112 for (auto saveInfo : asyncInfo->saveFileList) {
113 NVal objt = NVal::CreateObject(env);
114 objt.AddProp("srcUri", NVal::CreateUTF8String(env, saveInfo.srcUri).val_);
115 objt.AddProp("dstUri", NVal::CreateUTF8String(env, saveInfo.dstUri).val_);
116 objt.AddProp("status", NVal::CreateBool(env, saveInfo.status).val_);
117
118 napi_set_property(env, saveListNapi, NVal::CreateInt32(env, i).val_, objt.val_);
119 i = i + 1;
120 }
121 NVal objn = NVal::CreateObject(env);
122 objn.AddProp("saveFileList", saveListNapi);
123 CallBackSuccess(env, asyncInfo->callback[COMMON_NUM::ZERO], COMMON_NUM::ONE, objn.val_);
124 } else {
125 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "SaveFile fail", asyncInfo->err);
126 }
127 CallComplete(env, asyncInfo->callback[COMMON_NUM::TWO]);
128 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ZERO]);
129 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ONE]);
130 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::TWO]);
131 napi_delete_async_work(env, asyncInfo->asyncWork);
132 delete asyncInfo;
133 }
134
SearchFileExec(napi_env env,void * data)135 void SearchFileExec(napi_env env, void *data)
136 {
137 auto asyncInfo = (SearchFileAsyncInfo *)data;
138 unique_ptr<FileManager::StorageAbility> point;
139 vector<FileManager::FileInfo> result;
140 Uri uriObj(asyncInfo->path);
141 asyncInfo->err = point->SearchFiles(uriObj, asyncInfo->name, result);
142 asyncInfo->fileInfoList.assign(result.begin(), result.end());
143 }
144
SearchFileComp(napi_env env,napi_status status,void * data)145 void SearchFileComp(napi_env env, napi_status status, void *data)
146 {
147 auto asyncInfo = (SearchFileAsyncInfo *)data;
148 if (asyncInfo->err == ERROR_CODE::SUCCESS_CODE) {
149 napi_value fileListNapi;
150 napi_create_array(env, &fileListNapi);
151 int32_t i = 0;
152 for (auto fileInfo : asyncInfo->fileInfoList) {
153 NVal objt = NVal::CreateObject(env);
154 objt.AddProp("uri", NVal::CreateUTF8String(env, fileInfo.fileUri).val_);
155 objt.AddProp("name", NVal::CreateUTF8String(env, fileInfo.fileName).val_);
156
157 objt.AddProp("lastModifiedTime", NVal::CreateInt64(env, fileInfo.lastUseTime).val_);
158 objt.AddProp("length", NVal::CreateInt32(env, fileInfo.fileSize).val_);
159 objt.AddProp("num", NVal::CreateInt32(env, fileInfo.dirNum).val_);
160 string type = (fileInfo.typeDir == 1) ? "dir" : "file";
161 objt.AddProp("type", NVal::CreateUTF8String(env, type).val_);
162 objt.AddProp("suffix", NVal::CreateUTF8String(env, fileInfo.mimeType).val_);
163
164 napi_set_property(env, fileListNapi, NVal::CreateInt32(env, i).val_, objt.val_);
165 i = i + 1;
166 }
167 NVal objn = NVal::CreateObject(env);
168 objn.AddProp("fileList", fileListNapi);
169 CallBackSuccess(env, asyncInfo->callback[COMMON_NUM::ZERO], COMMON_NUM::ONE, objn.val_);
170 } else {
171 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "SearchFile fail", asyncInfo->err);
172 }
173 CallComplete(env, asyncInfo->callback[COMMON_NUM::TWO]);
174 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ZERO]);
175 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ONE]);
176 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::TWO]);
177 napi_delete_async_work(env, asyncInfo->asyncWork);
178 delete asyncInfo;
179 }
180
ListExec(napi_env env,void * data)181 void ListExec(napi_env env, void *data)
182 {
183 auto asyncInfo = (ListAsyncInfo *)data;
184 unique_ptr<FileManager::StorageAbility> point;
185 vector<FileManager::FileInfo> result;
186 Uri uriObj(asyncInfo->path);
187 asyncInfo->err = point->QueryFiles(uriObj, result);
188 asyncInfo->fileInfoList.assign(result.begin(), result.end());
189 }
190
ListComp(napi_env env,napi_status status,void * data)191 void ListComp(napi_env env, napi_status status, void *data)
192 {
193 auto asyncInfo = (ListAsyncInfo *)data;
194 if (asyncInfo->err == ERROR_CODE::SUCCESS_CODE) {
195 napi_value fileListNapi;
196 napi_create_array(env, &fileListNapi);
197 int32_t i = 0;
198 for (auto fileInfo : asyncInfo->fileInfoList) {
199 NVal objt = NVal::CreateObject(env);
200 objt.AddProp("uri", NVal::CreateUTF8String(env, fileInfo.fileUri).val_);
201 objt.AddProp("name", NVal::CreateUTF8String(env, fileInfo.fileName).val_);
202
203 objt.AddProp("lastModifiedTime", NVal::CreateInt64(env, fileInfo.lastUseTime).val_);
204 objt.AddProp("length", NVal::CreateInt32(env, fileInfo.fileSize).val_);
205 objt.AddProp("num", NVal::CreateInt32(env, fileInfo.dirNum).val_);
206 string type = (fileInfo.typeDir == 1) ? "dir" : "file";
207 objt.AddProp("type", NVal::CreateUTF8String(env, type).val_);
208 objt.AddProp("suffix", NVal::CreateUTF8String(env, fileInfo.mimeType).val_);
209
210 napi_set_property(env, fileListNapi, NVal::CreateInt32(env, i).val_, objt.val_);
211 i = i + 1;
212 }
213 NVal objn = NVal::CreateObject(env);
214 objn.AddProp("fileList", fileListNapi);
215 CallBackSuccess(env, asyncInfo->callback[COMMON_NUM::ZERO], COMMON_NUM::ONE, objn.val_);
216 } else {
217 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "List fail", asyncInfo->err);
218 }
219 CallComplete(env, asyncInfo->callback[COMMON_NUM::TWO]);
220 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ZERO]);
221 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ONE]);
222 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::TWO]);
223 napi_delete_async_work(env, asyncInfo->asyncWork);
224 delete asyncInfo;
225 }
226
GetDeviceInfoExec(napi_env env,void * data)227 void GetDeviceInfoExec(napi_env env, void *data)
228 {
229 auto asyncInfo = (GetDeviceAsyncInfo *)data;
230 unique_ptr<FileManager::StorageAbility> point;
231 vector<FileManager::RootInfo> result;
232 asyncInfo->err = point->QueryDeviceInfo(result);
233 asyncInfo->deviceInfoList.assign(result.begin(), result.end());
234 }
235
GetDeviceInfoComp(napi_env env,napi_status status,void * data)236 void GetDeviceInfoComp(napi_env env, napi_status status, void *data)
237 {
238 auto asyncInfo = (GetDeviceAsyncInfo *)data;
239 if (asyncInfo->err == ERROR_CODE::SUCCESS_CODE) {
240 napi_value deviceListNapi;
241 napi_create_array(env, &deviceListNapi);
242 int32_t i = 0;
243 for (auto deviceInfo : asyncInfo->deviceInfoList) {
244 NVal objt = NVal::CreateObject(env);
245 objt.AddProp("uri", NVal::CreateUTF8String(env, deviceInfo.path).val_);
246 objt.AddProp("deviceID", NVal::CreateUTF8String(env, deviceInfo.deviceId).val_);
247
248 objt.AddProp("mountID", NVal::CreateInt32(env, deviceInfo.mountFlags).val_);
249 objt.AddProp("diskID", NVal::CreateUTF8String(env, deviceInfo.diskId).val_);
250
251 napi_set_property(env, deviceListNapi, NVal::CreateInt32(env, i).val_, objt.val_);
252 i = i + 1;
253 }
254 NVal objn = NVal::CreateObject(env);
255 objn.AddProp("deviceList", deviceListNapi);
256 CallBackSuccess(env, asyncInfo->callback[COMMON_NUM::ZERO], COMMON_NUM::ONE, objn.val_);
257 } else {
258 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "GetDeviceInfo fail", asyncInfo->err);
259 }
260 CallComplete(env, asyncInfo->callback[COMMON_NUM::TWO]);
261 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ZERO]);
262 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ONE]);
263 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::TWO]);
264 napi_delete_async_work(env, asyncInfo->asyncWork);
265 delete asyncInfo;
266 }
267
Mkdir(napi_env env,napi_callback_info info)268 napi_value FilePickerExporter::Mkdir(napi_env env, napi_callback_info info)
269 {
270 NFuncArg funcArg(env, info);
271 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
272 UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
273 return nullptr;
274 }
275
276 auto *asyncInfo = new MkdirAsyncInfo;
277 bool succ = false;
278 tie(succ, asyncInfo->callback[COMMON_NUM::ZERO], asyncInfo->callback[COMMON_NUM::ONE],
279 asyncInfo->callback[COMMON_NUM::TWO]) = CommonFunc::GetCallbackHandles(env, funcArg[NARG_POS::FIRST]);
280
281 unique_ptr<char[]> uri = nullptr;
282 tie(succ, uri, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("uri").ToUTF8String();
283
284 asyncInfo->path = (uri == nullptr) ? "" : uri.get();
285
286 if (asyncInfo->path == "") {
287 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "uri cannot be empty",
288 ERROR_CODE::URI_PARAMER_ERROR);
289 delete asyncInfo;
290 return nullptr;
291 }
292
293 napi_create_async_work(
294 env, nullptr, NVal::CreateUTF8String(env, "Mkdir").val_,
295 [](napi_env env, void *data) {
296 auto *asyncInfo = (MkdirAsyncInfo *)data;
297 unique_ptr<FileManager::StorageAbility> point;
298 Uri uriObj(asyncInfo->path);
299 asyncInfo->err = point->CreateDir(uriObj);
300 },
301 [](napi_env env, napi_status status, void *data) {
302 auto *asyncInfo = (MkdirAsyncInfo *)data;
303 if (asyncInfo->err == ERROR_CODE::SUCCESS_CODE) {
304 CallBackSuccess(env, asyncInfo->callback[COMMON_NUM::ZERO], 0, nullptr);
305 } else {
306 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "Mkdir fail", asyncInfo->err);
307 }
308 CallComplete(env, asyncInfo->callback[COMMON_NUM::TWO]);
309 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ZERO]);
310 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::ONE]);
311 napi_delete_reference(env, asyncInfo->callback[COMMON_NUM::TWO]);
312 napi_delete_async_work(env, asyncInfo->asyncWork);
313 delete asyncInfo;
314 },
315 (void *)asyncInfo, &asyncInfo->asyncWork);
316 napi_queue_async_work(env, asyncInfo->asyncWork);
317
318 return NVal::CreateUndefined(env).val_;
319 }
320
SaveFile(napi_env env,napi_callback_info info)321 napi_value FilePickerExporter::SaveFile(napi_env env, napi_callback_info info)
322 {
323 NFuncArg funcArg(env, info);
324 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
325 UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
326 return nullptr;
327 }
328
329 auto *asyncInfo = new SaveFileAsyncInfo;
330
331 bool succ = false;
332 tie(succ, asyncInfo->callback[COMMON_NUM::ZERO], asyncInfo->callback[COMMON_NUM::ONE],
333 asyncInfo->callback[COMMON_NUM::TWO]) = CommonFunc::GetCallbackHandles(env, funcArg[NARG_POS::FIRST]);
334
335 unique_ptr<char[]> dstUri = nullptr;
336 tie(succ, dstUri, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("dstUri").ToUTF8String();
337
338 uint32_t srcLen = 0;
339 vector<string> srcPath;
340 NVal srcNapi = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("srcUri");
341 napi_get_array_length(env, srcNapi.val_, &srcLen);
342 for (uint32_t i = 0; i < srcLen; ++i) {
343 napi_value srcElementNapi;
344 unique_ptr<char[]> srcElement = nullptr;
345 napi_get_element(env, srcNapi.val_, i, &srcElementNapi);
346 tie(succ, srcElement, ignore) = NVal(env, srcElementNapi).ToUTF8String();
347 string path = (srcElement == nullptr) ? "" : srcElement.get();
348 srcPath.emplace_back(path);
349 }
350
351 asyncInfo->srcPath.assign(srcPath.begin(), srcPath.end());
352 asyncInfo->dstPath = (dstUri == nullptr) ? "" : dstUri.get();
353 asyncInfo->srcLen = srcLen;
354
355 if (asyncInfo->dstPath == "" || asyncInfo->srcPath.empty()) {
356 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "dstUri or srcUri cannot be empty",
357 ERROR_CODE::URI_PARAMER_ERROR);
358 delete asyncInfo;
359 return nullptr;
360 }
361
362 napi_create_async_work(env, nullptr, NVal::CreateUTF8String(env, "SaveFile").val_, SaveFileExec,
363 SaveFileComp, (void *)asyncInfo, &asyncInfo->asyncWork);
364 napi_queue_async_work(env, asyncInfo->asyncWork);
365
366 return NVal::CreateUndefined(env).val_;
367 }
368
SearchFile(napi_env env,napi_callback_info info)369 napi_value FilePickerExporter::SearchFile(napi_env env, napi_callback_info info)
370 {
371 NFuncArg funcArg(env, info);
372 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
373 UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
374 return nullptr;
375 }
376
377 auto *asyncInfo = new SearchFileAsyncInfo;
378 bool succ = false;
379 tie(succ, asyncInfo->callback[COMMON_NUM::ZERO], asyncInfo->callback[COMMON_NUM::ONE],
380 asyncInfo->callback[COMMON_NUM::TWO]) = CommonFunc::GetCallbackHandles(env, funcArg[NARG_POS::FIRST]);
381
382 unique_ptr<char[]> uri = nullptr;
383 tie(succ, uri, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("uri").ToUTF8String();
384
385 unique_ptr<char[]> name = nullptr;
386 tie(succ, name, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("name").ToUTF8String();
387
388 asyncInfo->path = (uri == nullptr) ? "" : uri.get();
389 asyncInfo->name = (name == nullptr) ? "" : name.get();
390
391 if (asyncInfo->path == "") {
392 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "uri cannot be empty",
393 ERROR_CODE::URI_PARAMER_ERROR);
394 delete asyncInfo;
395 return nullptr;
396 }
397
398 napi_create_async_work(env, nullptr, NVal::CreateUTF8String(env, "SearchFile").val_, SearchFileExec,
399 SearchFileComp, (void *)asyncInfo, &asyncInfo->asyncWork);
400 napi_queue_async_work(env, asyncInfo->asyncWork);
401
402 return NVal::CreateUndefined(env).val_;
403 }
404
List(napi_env env,napi_callback_info info)405 napi_value FilePickerExporter::List(napi_env env, napi_callback_info info)
406 {
407 NFuncArg funcArg(env, info);
408 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
409 UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
410 return nullptr;
411 }
412
413 auto *asyncInfo = new ListAsyncInfo;
414
415 bool succ = false;
416 tie(succ, asyncInfo->callback[COMMON_NUM::ZERO], asyncInfo->callback[COMMON_NUM::ONE],
417 asyncInfo->callback[COMMON_NUM::TWO]) = CommonFunc::GetCallbackHandles(env, funcArg[NARG_POS::FIRST]);
418
419 unique_ptr<char[]> uri = nullptr;
420 tie(succ, uri, ignore) = NVal(env, funcArg[NARG_POS::FIRST]).GetProp("uri").ToUTF8String();
421
422 asyncInfo->path = (uri == nullptr) ? "" : uri.get();
423 if (asyncInfo->path == "") {
424 CallBackError(env, asyncInfo->callback[COMMON_NUM::ONE], "uri cannot be empty",
425 ERROR_CODE::URI_PARAMER_ERROR);
426 delete asyncInfo;
427 return nullptr;
428 }
429
430 napi_create_async_work(env, nullptr, NVal::CreateUTF8String(env, "List").val_, ListExec, ListComp,
431 (void *)asyncInfo, &asyncInfo->asyncWork);
432 napi_queue_async_work(env, asyncInfo->asyncWork);
433
434 return NVal::CreateUndefined(env).val_;
435 }
436
GetDeviceInfo(napi_env env,napi_callback_info info)437 napi_value FilePickerExporter::GetDeviceInfo(napi_env env, napi_callback_info info)
438 {
439 NFuncArg funcArg(env, info);
440 if (!funcArg.InitArgs(NARG_CNT::ONE)) {
441 UniError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
442 return nullptr;
443 }
444
445 auto *asyncInfo = new GetDeviceAsyncInfo;
446
447 bool succ = false;
448 tie(succ, asyncInfo->callback[COMMON_NUM::ZERO], asyncInfo->callback[COMMON_NUM::ONE],
449 asyncInfo->callback[COMMON_NUM::TWO]) = CommonFunc::GetCallbackHandles(env, funcArg[NARG_POS::FIRST]);
450
451 napi_create_async_work(env, nullptr, NVal::CreateUTF8String(env, "GetDeviceInfo").val_, GetDeviceInfoExec,
452 GetDeviceInfoComp, (void *)asyncInfo, &asyncInfo->asyncWork);
453 napi_queue_async_work(env, asyncInfo->asyncWork);
454
455 return NVal::CreateUndefined(env).val_;
456 }
457
Export()458 bool FilePickerExporter::Export()
459 {
460 return exports_.AddProp(
461 { NVal::DeclareNapiFunction("mkdir", Mkdir), NVal::DeclareNapiFunction("saveFile", SaveFile),
462 NVal::DeclareNapiFunction("searchFile", SearchFile), NVal::DeclareNapiFunction("list", List),
463 NVal::DeclareNapiFunction("getDeviceInfo", GetDeviceInfo) });
464 }
465
GetClassName()466 string FilePickerExporter::GetClassName()
467 {
468 return FilePickerExporter::className_;
469 }
470
FilePickerExporter(napi_env env,napi_value exports)471 FilePickerExporter::FilePickerExporter(napi_env env, napi_value exports)
472 : NExporter(env, exports)
473 {}
474
~FilePickerExporter()475 FilePickerExporter::~FilePickerExporter() {}
476 } // namespace ModuleFPExpoter
477 } // namespace DistributedFS
478 } // namespace OHOS