• 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 
16 #include "sendfile_napi.h"
17 
18 #include "filemgmt_libn.h"
19 #include "send_file.h"
20 #include "trans_event.h"
21 #include "utils_log.h"
22 
23 namespace OHOS {
24 namespace Storage {
25 namespace DistributedFile {
26 using namespace FileManagement::LibN;
27 
GetJsPath(napi_env env,napi_value param)28 std::vector<std::string> GetJsPath(napi_env env, napi_value param)
29 {
30     std::vector<std::string> jsPath;
31     jsPath.clear();
32 
33     bool isArray = false;
34     if (napi_is_array(env, param, &isArray) != napi_ok || isArray == false) {
35         LOGE("JS sendFile filename must be a string array.");
36         return jsPath;
37     }
38 
39     uint32_t arraySize = 0;
40     if (napi_get_array_length(env, param, &arraySize) != napi_ok) {
41         LOGE("JS sendFile get filename array size failed.");
42         return jsPath;
43     }
44     if (arraySize > 1) {
45         return jsPath;
46     }
47     for (uint32_t i = 0; i < arraySize; ++i) {
48         napi_value result = nullptr;
49         napi_status status = napi_get_element(env, param, i, &result);
50         if (status == napi_ok && result != nullptr) {
51             bool succ = false;
52             std::unique_ptr<char []> path;
53             std::tie(succ, path, std::ignore) = NVal(env, result).ToUTF8String();
54             if (succ) {
55                 jsPath.push_back(path.get());
56             } else {
57                 LOGE("JS sendFile: only string array were accepted as filename para.");
58             }
59         }
60     }
61     return jsPath;
62 }
63 
JsSendFile(napi_env env,napi_callback_info info)64 napi_value JsSendFile(napi_env env, napi_callback_info info)
65 {
66     NFuncArg funcArg(env, info);
67     if (!funcArg.InitArgs(DFS_ARG_CNT::FOUR, DFS_ARG_CNT::FIVE)) {
68         NError(EINVAL).ThrowErr(env, "Number of arguments unmatched");
69         return nullptr;
70     }
71 
72     bool succ = false;
73     std::unique_ptr<char []> deviceId;
74     std::tie(succ, deviceId, std::ignore) = NVal(env, funcArg[DFS_ARG_POS::FIRST]).ToUTF8String();
75     std::string deviceIdString = "";
76     if (succ) {
77         deviceIdString =  std::string(deviceId.get());
78     }
79 
80     uint32_t fileCount = 0;
81     napi_status status = napi_get_value_uint32(env, funcArg[DFS_ARG_POS::FOURTH], &fileCount);
82     if (status != napi_ok && fileCount != 1) {
83         LOGE("JS sendFile: param fileCounts only accecpt 1.");
84         return nullptr;
85     }
86 
87     std::vector<std::string> sourPath = GetJsPath(env, funcArg[DFS_ARG_POS::SECOND]);
88     std::vector<std::string> destPath = GetJsPath(env, funcArg[DFS_ARG_POS::THIRD]);
89 
90     auto resultCode = std::make_shared<int32_t>();
91     auto cbExec = [deviceIdString, sourPath, destPath, fileCount, resultCode]() -> NError {
92         *resultCode = SendFile::ExecSendFile(deviceIdString.c_str(), sourPath, destPath, fileCount);
93         return NError(*resultCode);
94     };
95 
96     auto cbComplete = [resultCode](napi_env env, NError err) -> NVal {
97         if (err) {
98             return { env, err.GetNapiErr(env) };
99         }
100         return { NVal::CreateInt64(env, *resultCode) };
101     };
102 
103     std::string procedureName = "SendFile";
104     NVal thisVar(env, funcArg.GetThisVar());
105     if (funcArg.GetArgc() == DFS_ARG_CNT::FOUR) {
106         return NAsyncWorkPromise(env, thisVar).Schedule(procedureName, cbExec, cbComplete).val_;
107     } else if (funcArg.GetArgc() == DFS_ARG_CNT::FIVE) {
108         NVal cb(env, funcArg[DFS_ARG_POS::FIFTH]);
109         return NAsyncWorkCallback(env, thisVar, cb).Schedule(procedureName, cbExec, cbComplete).val_;
110     }
111 
112     return NVal::CreateUndefined(env).val_;
113 }
114 
JsOn(napi_env env,napi_callback_info cbinfo)115 napi_value JsOn(napi_env env, napi_callback_info cbinfo)
116 {
117     size_t requireArgc = 2;
118     size_t argc = 2;
119     napi_value argv[2] = { 0 };
120     napi_value thisVar = 0;
121     void* data = nullptr;
122     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, &data);
123 
124     EventAgent* agent = nullptr;
125     napi_unwrap(env, thisVar, (void**)&agent);
126 
127     NAPI_ASSERT(env, argc >= requireArgc, "requires 2 parameter");
128 
129     napi_valuetype eventValueType = napi_undefined;
130     napi_typeof(env, argv[0], &eventValueType);
131     NAPI_ASSERT(env, eventValueType == napi_string, "type mismatch for parameter 1");
132 
133     napi_valuetype eventHandleType = napi_undefined;
134     napi_typeof(env, argv[1], &eventHandleType);
135     NAPI_ASSERT(env, eventHandleType == napi_function, "type mismatch for parameter 2");
136 
137     char type[64] = { 0 };
138     size_t typeLen = 0;
139 
140     napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &typeLen);
141 
142     agent->On((const char*)type, argv[1]);
143 
144     napi_value result = nullptr;
145     napi_get_undefined(env, &result);
146     return result;
147 }
148 
JsOff(napi_env env,napi_callback_info cbinfo)149 napi_value JsOff(napi_env env, napi_callback_info cbinfo)
150 {
151     size_t requireArgc = 1;
152     size_t argc = 1;
153     napi_value argv[1] = { 0 };
154     napi_value thisVar = 0;
155     void* data = nullptr;
156     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, &data);
157 
158     EventAgent* agent = nullptr;
159     napi_unwrap(env, thisVar, (void**)&agent);
160 
161     NAPI_ASSERT(env, argc == requireArgc, "requires 1 parameter");
162 
163     napi_valuetype eventValueType = napi_undefined;
164     napi_typeof(env, argv[0], &eventValueType);
165     NAPI_ASSERT(env, eventValueType == napi_string, "type mismatch for parameter 1");
166 
167     char* type = nullptr;
168     size_t typeLen = 0;
169     napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typeLen);
170 
171     NAPI_ASSERT(env, typeLen > 0, "typeLen == 0");
172     type = new char[typeLen + 1];
173 
174     napi_get_value_string_utf8(env, argv[0], type, typeLen + 1, &typeLen);
175 
176     agent->Off(type);
177 
178     delete[] type;
179     napi_value result = nullptr;
180     napi_get_undefined(env, &result);
181     return result;
182 }
183 
JsConstructor(napi_env env,napi_callback_info cbinfo)184 napi_value JsConstructor(napi_env env, napi_callback_info cbinfo)
185 {
186     size_t argc = 2;
187     napi_value argv[2] = { nullptr };
188     napi_value thisVar = nullptr;
189     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
190 
191     char bundleName[SendFile::SENDFILE_NAPI_BUF_LENGTH] = { 0 };
192     size_t typeLen = 0;
193     napi_get_value_string_utf8(env, argv[0], bundleName, sizeof(bundleName), &typeLen);
194     LOGI("JsConstructor. [%{public}s]", bundleName);
195 
196     EventAgent* agent = new EventAgent(env, thisVar);
197     {
198         std::unique_lock<std::mutex> lock(SendFile::g_uidMutex);
199         if (SendFile::mapUidToEventAgent_.end() != SendFile::mapUidToEventAgent_.find(SendFile::BUNDLE_ID_)) {
200             delete SendFile::mapUidToEventAgent_[SendFile::BUNDLE_ID_];
201             SendFile::mapUidToEventAgent_.erase(SendFile::BUNDLE_ID_);
202         }
203         if (SendFile::mapUidToEventAgent_.size() <= SendFile::MAX_SEND_FILE_HAP_NUMBER) {
204             auto [ignored, inserted] = SendFile::mapUidToEventAgent_.insert(make_pair(SendFile::BUNDLE_ID_, agent));
205             if (!inserted) {
206                 LOGE("map env to event agent error.");
207                 return nullptr;
208             } else {
209                 LOGI("map size %{public}d", SendFile::mapUidToEventAgent_.size());
210             }
211         }
212     }
213 
214     napi_wrap(env, thisVar, agent,
215         [](napi_env env, void* data, void* hint) {
216             auto iter = SendFile::mapUidToEventAgent_.find(SendFile::BUNDLE_ID_);
217             if (SendFile::mapUidToEventAgent_.end() != iter) {
218                 auto agent = (EventAgent*)data;
219                 if (agent != nullptr) {
220                     std::unique_lock<std::mutex> lock(SendFile::g_uidMutex);
221                     agent->ClearDevice();
222                     SendFile::mapUidToEventAgent_.erase(SendFile::BUNDLE_ID_);
223                     delete agent;
224                 }
225             }
226         },
227         nullptr, nullptr);
228 
229     return thisVar;
230 }
231 
232 /***********************************************
233  * Module export and register
234  ***********************************************/
SendFileExport(napi_env env,napi_value exports)235 napi_value SendFileExport(napi_env env, napi_value exports)
236 {
237     const char className[] = "SendFile";
238     static napi_property_descriptor desc[] = {
239         DECLARE_NAPI_FUNCTION("sendFile", JsSendFile),
240         DECLARE_NAPI_FUNCTION("on", JsOn),
241         DECLARE_NAPI_FUNCTION("off", JsOff),
242     };
243     napi_value sendFileClass = nullptr;
244 
245     napi_define_class(env, className, sizeof(className), JsConstructor, nullptr,
246         sizeof(desc) / sizeof(desc[0]), desc, &sendFileClass);
247 
248     napi_set_named_property(env, exports, "SendFile", sendFileClass);
249 
250     SendFile::RegisterCallback();
251     return exports;
252 }
253 
254 NAPI_MODULE(sendfile, SendFileExport)
255 } // namespace DistributedFile
256 } // namespace Storage
257 } // namespace OHOS