• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 #include "async_call.h"
16 #include "napi_common_want.h"
17 #include "paste_data_record.h"
18 #include "pasteboard_common.h"
19 #include "pasteboard_hilog.h"
20 #include "pasteboard_js_err.h"
21 #include "pastedata_napi.h"
22 #include "pastedata_record_napi.h"
23 
24 using namespace OHOS::MiscServices;
25 using namespace OHOS::Media;
26 
27 namespace OHOS {
28 namespace MiscServicesNapi {
29 static thread_local napi_ref g_pasteDataRecord = nullptr;
30 const int ARGC_TYPE_SET0 = 0;
31 const int ARGC_TYPE_SET1 = 1;
32 constexpr int32_t MIMETYPE_MAX_SIZE = 1024;
33 
PasteDataRecordNapi()34 PasteDataRecordNapi::PasteDataRecordNapi() : env_(nullptr)
35 {
36 }
37 
~PasteDataRecordNapi()38 PasteDataRecordNapi::~PasteDataRecordNapi()
39 {
40 }
41 
NewInstanceByRecord(napi_env env,napi_value & instance,const std::shared_ptr<MiscServices::PasteDataRecord> & record)42 bool PasteDataRecordNapi::NewInstanceByRecord(
43     napi_env env, napi_value &instance, const std::shared_ptr<MiscServices::PasteDataRecord> &record)
44 {
45     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
46     PasteDataRecordNapi *obj = nullptr;
47     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
48     if ((status != napi_ok) || (obj == nullptr)) {
49         return false;
50     }
51     obj->value_ = record;
52     obj->JSFillInstance(env, instance);
53     return true;
54 }
55 
NewHtmlTextRecordInstance(napi_env env,const std::string & text,napi_value & instance)56 bool PasteDataRecordNapi::NewHtmlTextRecordInstance(napi_env env, const std::string &text, napi_value &instance)
57 {
58     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
59     PasteDataRecordNapi *obj = nullptr;
60     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
61     if ((status != napi_ok) || (obj == nullptr)) {
62         return false;
63     }
64     obj->value_ = PasteboardClient::GetInstance()->CreateHtmlTextRecord(text);
65     obj->JSFillInstance(env, instance);
66     return true;
67 }
68 
NewPlainTextRecordInstance(napi_env env,const std::string & text,napi_value & instance)69 bool PasteDataRecordNapi::NewPlainTextRecordInstance(napi_env env, const std::string &text, napi_value &instance)
70 {
71     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
72     PasteDataRecordNapi *obj = nullptr;
73     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
74     if ((status != napi_ok) || (obj == nullptr)) {
75         return false;
76     }
77     obj->value_ = PasteboardClient::GetInstance()->CreatePlainTextRecord(text);
78     obj->JSFillInstance(env, instance);
79     return true;
80 }
81 
NewPixelMapRecordInstance(napi_env env,const std::shared_ptr<PixelMap> pixelMap,napi_value & instance)82 bool PasteDataRecordNapi::NewPixelMapRecordInstance(
83     napi_env env, const std::shared_ptr<PixelMap> pixelMap, napi_value &instance)
84 {
85     if (pixelMap == nullptr) {
86         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "pixelMap is nullptr.");
87         return false;
88     }
89 
90     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
91     PasteDataRecordNapi *obj = nullptr;
92     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
93     if ((status != napi_ok) || (obj == nullptr)) {
94         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed.");
95         return false;
96     }
97     obj->value_ = PasteboardClient::GetInstance()->CreatePixelMapRecord(pixelMap);
98     obj->JSFillInstance(env, instance);
99     return true;
100 }
101 
NewUriRecordInstance(napi_env env,const std::string & text,napi_value & instance)102 bool PasteDataRecordNapi::NewUriRecordInstance(napi_env env, const std::string &text, napi_value &instance)
103 {
104     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
105     PasteDataRecordNapi *obj = nullptr;
106     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
107     if ((status != napi_ok) || (obj == nullptr)) {
108         return false;
109     }
110     obj->value_ = PasteboardClient::GetInstance()->CreateUriRecord(OHOS::Uri(text));
111     obj->JSFillInstance(env, instance);
112     return true;
113 }
114 
NewWantRecordInstance(napi_env env,const std::shared_ptr<OHOS::AAFwk::Want> want,napi_value & instance)115 bool PasteDataRecordNapi::NewWantRecordInstance(
116     napi_env env, const std::shared_ptr<OHOS::AAFwk::Want> want, napi_value &instance)
117 {
118     if (!want) {
119         return false;
120     }
121 
122     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
123     PasteDataRecordNapi *obj = nullptr;
124     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
125     if ((status != napi_ok) || (obj == nullptr)) {
126         return false;
127     }
128     obj->value_ = PasteboardClient::GetInstance()->CreateWantRecord(want);
129     obj->JSFillInstance(env, instance);
130     return true;
131 }
132 
NewKvRecordInstance(napi_env env,const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer,napi_value & instance)133 bool PasteDataRecordNapi::NewKvRecordInstance(
134     napi_env env, const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer, napi_value &instance)
135 {
136     NAPI_CALL_BASE(env, PasteDataRecordNapi::NewInstance(env, instance), false);
137     PasteDataRecordNapi *obj = nullptr;
138     napi_status status = napi_unwrap(env, instance, reinterpret_cast<void **>(&obj));
139     if ((status != napi_ok) || (obj == nullptr)) {
140         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "unwrap failed");
141         return false;
142     }
143     obj->value_ = PasteboardClient::GetInstance()->CreateKvRecord(mimeType, arrayBuffer);
144     obj->JSFillInstance(env, instance);
145     return true;
146 }
147 
SetNamedPropertyByStr(napi_env env,napi_value & instance,const char * propName,const char * propValue)148 void PasteDataRecordNapi::SetNamedPropertyByStr(
149     napi_env env, napi_value &instance, const char *propName, const char *propValue)
150 {
151     if (propName == nullptr || propValue == nullptr) {
152         return;
153     }
154     napi_value prop = nullptr;
155     if (napi_create_string_utf8(env, propValue, NAPI_AUTO_LENGTH, &prop) == napi_ok) {
156         napi_set_named_property(env, instance, propName, prop);
157     }
158 }
159 
SetNapiKvData(napi_env env,std::shared_ptr<MineCustomData> customData)160 napi_value PasteDataRecordNapi::SetNapiKvData(napi_env env, std::shared_ptr<MineCustomData> customData)
161 {
162     if (customData == nullptr) {
163         return nullptr;
164     }
165     napi_value jsCustomData = nullptr;
166     napi_create_object(env, &jsCustomData);
167     auto itemData = customData->GetItemData();
168     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "size = %{public}d.", static_cast<uint32_t>(itemData.size()));
169     for (auto &item : itemData) {
170         void *data = nullptr;
171         napi_value arrayBuffer = nullptr;
172         size_t len = item.second.size();
173         NAPI_CALL(env, napi_create_arraybuffer(env, len, &data, &arrayBuffer));
174         if (memcpy_s(data, len, reinterpret_cast<const void *>(item.second.data()), len) != 0) {
175             return nullptr;
176         }
177         NAPI_CALL(env, napi_set_named_property(env, jsCustomData, item.first.c_str(), arrayBuffer));
178         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "mimeType = %{public}s.", item.first.c_str());
179     }
180     return jsCustomData;
181 }
182 
GetNativeKvData(napi_env env,napi_value napiValue)183 std::shared_ptr<MineCustomData> PasteDataRecordNapi::GetNativeKvData(napi_env env, napi_value napiValue)
184 {
185     napi_valuetype valueType = napi_undefined;
186     NAPI_CALL(env, napi_typeof(env, napiValue, &valueType));
187     NAPI_ASSERT(env, valueType == napi_object, "Wrong argument type. Object expected.");
188 
189     napi_value mimeTypes = nullptr;
190     NAPI_CALL(env, napi_get_property_names(env, napiValue, &mimeTypes));
191     uint32_t mimeTypesNum = 0;
192     NAPI_CALL(env, napi_get_array_length(env, mimeTypes, &mimeTypesNum));
193 
194     PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "mimeTypesNum = %{public}u", mimeTypesNum);
195     std::shared_ptr<MineCustomData> customData = std::make_shared<MineCustomData>();
196     for (uint32_t i = 0; i < mimeTypesNum; i++) {
197         napi_value mimeTypeNapi = nullptr;
198         NAPI_CALL(env, napi_get_element(env, mimeTypes, i, &mimeTypeNapi));
199 
200         std::string mimeType;
201         bool ret = GetValue(env, mimeTypeNapi, mimeType);
202         if (!ret || (mimeType.size() > MIMETYPE_MAX_SIZE) || mimeType == "") {
203             return nullptr;
204         }
205         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "mimeType = %{public}s,", mimeType.c_str());
206 
207         napi_value napiArrayBuffer = nullptr;
208         NAPI_CALL(env, napi_get_property(env, napiValue, mimeTypeNapi, &napiArrayBuffer));
209         void *data = nullptr;
210         size_t dataLen;
211         NAPI_CALL(env, napi_get_arraybuffer_info(env, napiArrayBuffer, &data, &dataLen));
212         customData->AddItemData(mimeType,
213             std::vector<uint8_t>(reinterpret_cast<uint8_t *>(data), reinterpret_cast<uint8_t *>(data) + dataLen));
214     }
215     return customData;
216 }
217 
JSFillInstance(napi_env env,napi_value & instance)218 void PasteDataRecordNapi::JSFillInstance(napi_env env, napi_value &instance)
219 {
220     if (value_ == nullptr) {
221         return;
222     }
223     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "mimeType = %{public}s.", value_->GetMimeType().c_str());
224 
225     auto mimeType = value_->GetMimeType();
226     SetNamedPropertyByStr(env, instance, "mimeType", mimeType.c_str());
227 
228     auto plainText = value_->GetPlainText();
229     if (plainText != nullptr) {
230         SetNamedPropertyByStr(env, instance, "plainText", plainText->c_str());
231         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill plainText.");
232     }
233 
234     auto htmlText = value_->GetHtmlText();
235     if (htmlText != nullptr) {
236         SetNamedPropertyByStr(env, instance, "htmlText", htmlText->c_str());
237         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill htmlText.");
238     }
239 
240     auto uri = value_->GetUri();
241     if (uri != nullptr) {
242         SetNamedPropertyByStr(env, instance, "uri", uri->ToString().c_str());
243         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill uri.");
244     }
245 
246     auto want = value_->GetWant();
247     if (want != nullptr) {
248         napi_value jsWant = OHOS::AppExecFwk::WrapWant(env, *want);
249         napi_set_named_property(env, instance, "want", jsWant);
250         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill want.");
251     }
252 
253     auto pixelMap = value_->GetPixelMap();
254     if (pixelMap != nullptr) {
255         napi_value jsPixelMap = OHOS::Media::PixelMapNapi::CreatePixelMap(env, pixelMap);
256         napi_set_named_property(env, instance, "pixelMap", jsPixelMap);
257         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill pixelMap.");
258     }
259 
260     auto customData = value_->GetCustomData();
261     if (customData != nullptr) {
262         napi_value jsCustomData = PasteDataRecordNapi::SetNapiKvData(env, customData);
263         napi_set_named_property(env, instance, "data", jsCustomData);
264         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "fill data.");
265     }
266 }
267 
ConvertToText(napi_env env,napi_callback_info info)268 napi_value PasteDataRecordNapi::ConvertToText(napi_env env, napi_callback_info info)
269 {
270     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ConvertToText is called!");
271 
272     struct ExeContext {
273         std::string text;
274         PasteDataRecordNapi *obj = nullptr;
275     };
276     auto exeContext = std::make_shared<ExeContext>();
277     auto input = [exeContext](napi_env env, size_t argc, napi_value *argv, napi_value self) -> napi_status {
278         // convertToText(callback: AsyncCallback<string>) has 1 args
279         if (argc > 0 &&
280             !CheckArgsType(env, argv[0], napi_function, "Parameter error. The type of callback must be function.")) {
281             return napi_invalid_arg;
282         }
283         PasteDataRecordNapi *obj = nullptr;
284         napi_status status = napi_unwrap(env, self, reinterpret_cast<void **>(&obj));
285         if (status == napi_ok || obj != nullptr) {
286             exeContext->obj = obj;
287         }
288         return napi_ok;
289     };
290 
291     auto exec = [exeContext](AsyncCall::Context *ctx) {
292         if ((exeContext->obj != nullptr) && (exeContext->obj->value_ != nullptr)) {
293             exeContext->text = exeContext->obj->value_->ConvertToText();
294         }
295     };
296     auto output = [exeContext](napi_env env, napi_value *result) -> napi_status {
297         napi_status status =
298             napi_create_string_utf8(env, (exeContext->text).c_str(), (exeContext->text).length(), result);
299         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "napi_create_string_utf8 status = %{public}d", status);
300         return status;
301     };
302 
303     // 0: the AsyncCall at the first position;
304     AsyncCall asyncCall(env, info, std::make_shared<AsyncCall::Context>(std::move(input), std::move(output)), 0);
305     return asyncCall.Call(env, exec);
306 }
307 
ConvertToTextV9(napi_env env,napi_callback_info info)308 napi_value PasteDataRecordNapi::ConvertToTextV9(napi_env env, napi_callback_info info)
309 {
310     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ConvertToTextV9 is called!");
311     return ConvertToText(env, info);
312 }
313 
ToPlainText(napi_env env,napi_callback_info info)314 napi_value PasteDataRecordNapi::ToPlainText(napi_env env, napi_callback_info info)
315 {
316     PASTEBOARD_HILOGI(PASTEBOARD_MODULE_JS_NAPI, "ToPlainText is called!");
317     size_t argc = 1;
318     napi_value argv[1] = { 0 };
319     napi_value thisVar = nullptr;
320 
321     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
322     NAPI_ASSERT(env, argc >= ARGC_TYPE_SET0, "Wrong number of arguments");
323 
324     PasteDataRecordNapi *obj = nullptr;
325     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
326     if ((status != napi_ok) || (obj == nullptr)) {
327         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Get ToPlainText object failed");
328         return nullptr;
329     }
330 
331     std::string str = obj->value_->ConvertToText();
332     napi_value result = nullptr;
333     napi_create_string_utf8(env, str.c_str(), NAPI_AUTO_LENGTH, &result);
334     return result;
335 }
336 
PasteDataRecordInit(napi_env env,napi_value exports)337 napi_value PasteDataRecordNapi::PasteDataRecordInit(napi_env env, napi_value exports)
338 {
339     napi_property_descriptor properties[] = {
340         DECLARE_NAPI_FUNCTION("convertToText", ConvertToText),
341         DECLARE_NAPI_FUNCTION("convertToTextV9", ConvertToTextV9),
342         DECLARE_NAPI_FUNCTION("toPlainText", ToPlainText)
343     };
344 
345     napi_status status = napi_ok;
346 
347     napi_value constructor;
348     status = napi_define_class(env, "PasteDataRecord", NAPI_AUTO_LENGTH, New, nullptr,
349         sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
350     if (status != napi_ok) {
351         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "Failed to define class at PasteDataRecordInit");
352         return nullptr;
353     }
354 
355     status = napi_create_reference(env, constructor, 1, &g_pasteDataRecord);
356     if (status != napi_ok) {
357         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "PasteDataRecordInit create reference failed");
358         return nullptr;
359     }
360     napi_set_named_property(env, exports, "PasteDataRecord", constructor);
361     return exports;
362 }
363 
Destructor(napi_env env,void * nativeObject,void * finalize_hint)364 void PasteDataRecordNapi::Destructor(napi_env env, void *nativeObject, void *finalize_hint)
365 {
366     PASTEBOARD_HILOGD(PASTEBOARD_MODULE_JS_NAPI, "Destructor");
367     PasteDataRecordNapi *obj = static_cast<PasteDataRecordNapi *>(nativeObject);
368     delete obj;
369 }
370 
New(napi_env env,napi_callback_info info)371 napi_value PasteDataRecordNapi::New(napi_env env, napi_callback_info info)
372 {
373     size_t argc = ARGC_TYPE_SET1;
374     napi_value argv[1] = { 0 };
375     napi_value thisVar = nullptr;
376     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
377 
378     // get native object
379     PasteDataRecordNapi *obj = new PasteDataRecordNapi();
380     obj->env_ = env;
381     NAPI_CALL(env, napi_wrap(env, thisVar, obj, PasteDataRecordNapi::Destructor, nullptr, nullptr));
382     return thisVar;
383 }
384 
NewInstance(napi_env env,napi_value & instance)385 napi_status PasteDataRecordNapi::NewInstance(napi_env env, napi_value &instance)
386 {
387     napi_status status = napi_invalid_arg;
388 
389     napi_value constructor;
390     status = napi_get_reference_value(env, g_pasteDataRecord, &constructor);
391     if (status != napi_ok) {
392         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "get reference failed");
393         return status;
394     }
395 
396     status = napi_new_instance(env, constructor, 0, nullptr, &instance);
397     if (status != napi_ok) {
398         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_JS_NAPI, "new instance failed");
399         return status;
400     }
401 
402     return napi_ok;
403 }
404 } // namespace MiscServicesNapi
405 } // namespace OHOS
406