• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #define MLOG_TAG "ScannerNapi"
16 
17 #include "media_scanner_napi.h"
18 #include "media_library_napi.h"
19 #include "medialibrary_db_const.h"
20 #include "medialibrary_errno.h"
21 #include "medialibrary_napi_log.h"
22 #include "userfile_client.h"
23 
24 using OHOS::HiviewDFX::HiLog;
25 using OHOS::HiviewDFX::HiLogLabel;
26 using namespace std;
27 
28 namespace OHOS {
29 namespace Media {
30 thread_local napi_ref MediaScannerNapi::sConstructor_ = nullptr;
31 
MediaScannerNapi()32 MediaScannerNapi::MediaScannerNapi()
33     : env_(nullptr) {}
34 
~MediaScannerNapi()35 MediaScannerNapi::~MediaScannerNapi()
36 {}
37 
Init(napi_env env,napi_value exports)38 napi_value MediaScannerNapi::Init(napi_env env, napi_value exports)
39 {
40     napi_status status;
41     napi_value ctorObj;
42     int32_t refCount = 1;
43 
44     napi_property_descriptor scanner_props[] = {
45         DECLARE_NAPI_FUNCTION("scanDir", ScanDir),
46         DECLARE_NAPI_FUNCTION("scanFile", ScanFile)
47     };
48 
49     napi_property_descriptor static_prop[] = {
50         DECLARE_NAPI_STATIC_FUNCTION("getScannerInstance", GetMediaScannerInstance)
51     };
52 
53     status = napi_define_class(env, SCANNER_HELPER_NAPI_CLASS_NAME.c_str(), NAPI_AUTO_LENGTH,
54         MediaScannerNapiConstructor, nullptr, sizeof(scanner_props) / sizeof(scanner_props[PARAM0]),
55         scanner_props, &ctorObj);
56     if (status == napi_ok) {
57         if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
58             status = napi_set_named_property(env, exports, SCANNER_HELPER_NAPI_CLASS_NAME.c_str(), ctorObj);
59             if (status == napi_ok && napi_define_properties(env, exports,
60                 sizeof(static_prop) / sizeof(static_prop[PARAM0]), static_prop) == napi_ok) {
61                 return exports;
62             }
63         }
64     }
65     return nullptr;
66 }
67 
MediaScannerNapiConstructor(napi_env env,napi_callback_info info)68 napi_value MediaScannerNapi::MediaScannerNapiConstructor(napi_env env, napi_callback_info info)
69 {
70     napi_status status;
71     napi_value result = nullptr;
72     napi_value thisVar = nullptr;
73 
74     napi_get_undefined(env, &result);
75     GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
76 
77     if (status == napi_ok && thisVar != nullptr) {
78         unique_ptr<MediaScannerNapi> obj = make_unique<MediaScannerNapi>();
79         if (obj != nullptr) {
80             obj->env_ = env;
81 
82             obj->mediaScannerNapiCallbackObj_ = std::make_shared<MediaScannerNapiCallback>(env);
83             if (obj->mediaScannerNapiCallbackObj_ == nullptr) {
84                 NAPI_ERR_LOG("[MediaScannerNapiConstructor] callback instance creation failed!");
85                 return result;
86             }
87 
88             status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
89                                MediaScannerNapi::MediaScannerNapiDestructor, nullptr, nullptr);
90             if (status == napi_ok) {
91                 obj.release();
92                 return thisVar;
93             } else {
94                 NAPI_ERR_LOG("Failed to wrap the native media scanner client, status: %{private}d", status);
95             }
96         }
97     }
98 
99     NAPI_INFO_LOG("[MediaScannerNapiConstructor] failed");
100     return result;
101 }
102 
MediaScannerNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)103 void MediaScannerNapi::MediaScannerNapiDestructor(napi_env env, void *nativeObject, void *finalize_hint)
104 {
105     MediaScannerNapi *scannerHelper = reinterpret_cast<MediaScannerNapi*>(nativeObject);
106     if (scannerHelper != nullptr) {
107         delete scannerHelper;
108     }
109 }
110 
GetMediaScannerInstance(napi_env env,napi_callback_info info)111 napi_value MediaScannerNapi::GetMediaScannerInstance(napi_env env, napi_callback_info info)
112 {
113     napi_status status;
114     napi_value result = nullptr;
115     napi_value ctor;
116     size_t argc = ARGS_ONE;
117     napi_value argv[ARGS_ONE] = {0};
118     napi_value thisVar = nullptr;
119 
120     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
121     status = napi_get_reference_value(env, sConstructor_, &ctor);
122     if (status == napi_ok) {
123         status = napi_new_instance(env, ctor, argc, argv, &result);
124         if (status == napi_ok) {
125             NAPI_INFO_LOG("[GetMediaScannerInstance] success");
126             return result;
127         } else {
128             NAPI_ERR_LOG("[GetMediaScannerInstance] New instance could not be obtained, status: %{public}d", status);
129         }
130     }
131 
132     NAPI_ERR_LOG("[GetMediaScannerInstance] failed , status = %{public}d", status);
133     napi_get_undefined(env, &result);
134     return result;
135 }
136 
InvokeJSCallback(napi_env env,const int32_t errCode,const std::string & uri,napi_ref callbackRef)137 void InvokeJSCallback(napi_env env, const int32_t errCode, const std::string &uri, napi_ref callbackRef)
138 {
139     napi_value retVal = nullptr;
140     napi_value results[ARGS_TWO] = {nullptr};
141     napi_get_undefined(env, &results[PARAM0]);
142     napi_create_object(env, &results[PARAM1]);
143 
144     napi_value jsStatus = 0;
145     napi_create_int32(env, errCode, &jsStatus);
146     napi_set_named_property(env, results[PARAM1], "status", jsStatus);
147 
148     napi_value jsUri = 0;
149     napi_create_string_utf8(env, uri.c_str(), NAPI_AUTO_LENGTH, &jsUri);
150     napi_set_named_property(env, results[PARAM1], "fileUri", jsUri);
151 
152     napi_value callback = nullptr;
153     napi_get_reference_value(env, callbackRef, &callback);
154     napi_call_function(env, nullptr, callback, ARGS_TWO, results, &retVal);
155 }
156 
NapiScanUtils(napi_env env,napi_callback_info info,const string & scanType)157 napi_value MediaScannerNapi::NapiScanUtils(napi_env env, napi_callback_info info, const string &scanType)
158 {
159     char buffer[PATH_MAX];
160     napi_status status;
161     napi_value result = nullptr;
162     size_t argc = ARGS_TWO;
163     napi_value argv[ARGS_TWO] = {0};
164     napi_value thisVar = nullptr;
165     MediaScannerNapi *obj = nullptr;
166     string event = "";
167     napi_ref callbackRef = nullptr;
168     const int32_t refCount = 1;
169     size_t res = 0;
170     int32_t errCode = 0;
171 
172     GET_JS_ARGS(env, info, argc, argv, thisVar);
173     NAPI_ASSERT(env, argc == ARGS_TWO, "requires 2 parameters");
174 
175     NAPI_INFO_LOG("[MediaScannerNapi::NapiScanUtils] start");
176     napi_get_undefined(env, &result);
177     status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&obj));
178     if (status == napi_ok && obj != nullptr) {
179         if (argc == ARGS_TWO) {
180             napi_valuetype valueType = napi_undefined;
181             napi_typeof(env, argv[PARAM0], &valueType);
182             if (valueType == napi_string) {
183                 napi_get_value_string_utf8(env, argv[PARAM0], buffer, PATH_MAX, &res);
184                 event = string(buffer);
185             } else {
186                 NAPI_ERR_LOG("Invalid arg, valueType: %{public}d", valueType);
187                 return result;
188             }
189             napi_typeof(env, argv[PARAM1], &valueType);
190             if (valueType == napi_function) {
191                 napi_create_reference(env, argv[PARAM1], refCount, &callbackRef);
192             } else {
193                 NAPI_ERR_LOG("Invalid arg, valueType: %{public}d", valueType);
194                 return result;
195             }
196         }
197         errCode = 0;
198         DataShareScanBoardcast(event);
199 
200         if (errCode == 0) {
201             obj->mediaScannerNapiCallbackObj_->SetToMap(event, callbackRef);
202         } else {
203             // Invoke JS callback functions based on results
204             InvokeJSCallback(env, errCode, "", callbackRef);
205         }
206     }
207     NAPI_INFO_LOG("[MediaScannerNapi::NapiScanUtils] end");
208     return result;
209 }
210 
ScanFile(napi_env env,napi_callback_info info)211 napi_value MediaScannerNapi::ScanFile(napi_env env, napi_callback_info info)
212 {
213     return NapiScanUtils(env, info, "FILE");
214 }
215 
ScanDir(napi_env env,napi_callback_info info)216 napi_value MediaScannerNapi::ScanDir(napi_env env, napi_callback_info info)
217 {
218     return NapiScanUtils(env, info, "DIR");
219 }
220 
DataShareScanBoardcast(const std::string & event)221 void MediaScannerNapi::DataShareScanBoardcast(const std::string &event)
222 {
223     NAPI_INFO_LOG("MediaScannerNapi::DataShareScanBoardcast start, event: %{public}s", event.c_str());
224     Uri insertUri(MEDIALIBRARY_DATA_URI + "/" + MEDIA_BOARDCASTOPRN + "/" + MEDIA_SCAN_OPERATION);
225     OHOS::DataShare::DataShareValuesBucket valuesBucket;
226     valuesBucket.Put(MEDIA_DATA_DB_RELATIVE_PATH, event);
227     int index = UserFileClient::Insert(insertUri, valuesBucket);
228     if (index < 0) {
229         NAPI_ERR_LOG("[MediaScannerNapi::DataShareScanBoardcast return status %{public}d", index);
230     } else {
231         NAPI_INFO_LOG("[MediaScannerNapi::DataShareScanBoardcast success");
232     }
233 }
234 
OnScanFinished(const int32_t status,const std::string & uri,const std::string & path)235 int32_t MediaScannerNapiCallback::OnScanFinished(const int32_t status, const std::string &uri, const std::string &path)
236 {
237     auto itr = scannerMap_.find(path);
238     if (itr != scannerMap_.end()) {
239         // Invoke JS callback functions based on results
240         InvokeJSCallback(env_, status, uri, itr->second);
241         scannerMap_.erase(path);
242         NAPI_DEBUG_LOG("OnScanFinished exit");
243     }
244 
245     return 0;
246 }
247 
SetToMap(const std::string & path,const napi_ref & cbRef)248 void MediaScannerNapiCallback::SetToMap(const std::string &path, const napi_ref &cbRef)
249 {
250     scannerMap_.insert(std::make_pair(path, cbRef));
251 }
252 } // namespace Media
253 } // namespace OHOS
254