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 "udmf_impl.h"
17
18 #include <memory>
19 #include <unordered_map>
20 #include <variant>
21
22 #include "html.h"
23 #include "image.h"
24 #include "link.h"
25 #include "summary_napi.h"
26 #include "system_defined_form.h"
27 #include "system_defined_pixelmap.h"
28 #include "text.h"
29 #include "plain_text.h"
30 #include "udmf_client.h"
31 #include "application_defined_record.h"
32 #include "async_task_params.h"
33 #include "data_params_conversion.h"
34 #include "get_data_params_napi.h"
35 #include "udmf_async_client.h"
36 #include "unified_data.h"
37 #include "unified_data_napi.h"
38 #include "unified_types.h"
39 #include "video.h"
40 #include "native_engine/native_engine.h"
41 #include "frameworks/bridge/common/utils/engine_helper.h"
42 #include "frameworks/bridge/common/utils/utils.h"
43 #include "frameworks/bridge/js_frontend/engine/common/js_engine.h"
44 #include "js_native_api_types.h"
45
46 #include "base/image/file_uri_helper.h"
47 #include "base/utils/utils.h"
48 #include "core/common/udmf/unified_data.h"
49 #include "ndk_data_conversion.h"
50 namespace OHOS::Ace {
GetInstance()51 UdmfClient* UdmfClient::GetInstance()
52 {
53 static UdmfClientImpl instance;
54 return &instance;
55 }
56
CreateUnifiedData()57 RefPtr<UnifiedData> UdmfClientImpl::CreateUnifiedData()
58 {
59 return AceType::DynamicCast<UnifiedData>(AceType::MakeRefPtr<UnifiedDataImpl>());
60 }
61
TransformUnifiedData(napi_value napiValue)62 RefPtr<UnifiedData> UdmfClientImpl::TransformUnifiedData(napi_value napiValue)
63 {
64 auto engine = EngineHelper::GetCurrentEngine();
65 CHECK_NULL_RETURN(engine, nullptr);
66 NativeEngine* nativeEngine = engine->GetNativeEngine();
67 napi_env env = reinterpret_cast<napi_env>(nativeEngine);
68 void* native = nullptr;
69 napi_unwrap(env, napiValue, &native);
70 auto* unifiedData = reinterpret_cast<UDMF::UnifiedDataNapi*>(native);
71 CHECK_NULL_RETURN(unifiedData, nullptr);
72 CHECK_NULL_RETURN(unifiedData->value_, nullptr);
73 auto udData = AceType::MakeRefPtr<UnifiedDataImpl>();
74 udData->SetUnifiedData(unifiedData->value_);
75 return udData;
76 }
77
TransformUdmfUnifiedData(RefPtr<UnifiedData> & UnifiedData)78 napi_value UdmfClientImpl::TransformUdmfUnifiedData(RefPtr<UnifiedData>& UnifiedData)
79 {
80 auto engine = EngineHelper::GetCurrentEngine();
81 CHECK_NULL_RETURN(engine, nullptr);
82 NativeEngine* nativeEngine = engine->GetNativeEngine();
83 napi_env env = reinterpret_cast<napi_env>(nativeEngine);
84 auto unifiedData = AceType::DynamicCast<UnifiedDataImpl>(UnifiedData)->GetUnifiedData();
85 CHECK_NULL_RETURN(unifiedData, nullptr);
86 napi_value dataVal = nullptr;
87 UDMF::UnifiedDataNapi::NewInstance(env, unifiedData, dataVal);
88 CHECK_NULL_RETURN(dataVal, nullptr);
89 return dataVal;
90 }
91
TransformUnifiedDataPtr(RefPtr<UnifiedData> & unifiedDataImpl)92 void* UdmfClientImpl::TransformUnifiedDataPtr(RefPtr<UnifiedData>& unifiedDataImpl)
93 {
94 CHECK_NULL_RETURN(unifiedDataImpl, nullptr);
95 std::shared_ptr<UDMF::UnifiedData> unifiedData =
96 AceType::DynamicCast<UnifiedDataImpl>(unifiedDataImpl)->GetUnifiedData();
97 CHECK_NULL_RETURN(unifiedData, nullptr);
98 return unifiedData.get();
99 }
100
TransformUnifiedDataForNative(void * rawData)101 RefPtr<UnifiedData> UdmfClientImpl::TransformUnifiedDataForNative(void* rawData)
102 {
103 CHECK_NULL_RETURN(rawData, nullptr);
104 auto udData = AceType::MakeRefPtr<UnifiedDataImpl>();
105 auto udmfData = static_cast<OH_UdmfData*>(rawData);
106 CHECK_NULL_RETURN(udmfData, nullptr);
107 auto unifiedData = std::make_shared<UDMF::UnifiedData>();
108 auto status = OHOS::UDMF::NdkDataConversion::GetNativeUnifiedData(udmfData, unifiedData);
109 if (status) {
110 return nullptr;
111 }
112
113 udData->SetUnifiedData(unifiedData);
114 return udData;
115 }
116
TransformSummary(std::map<std::string,int64_t> & summary)117 napi_value UdmfClientImpl::TransformSummary(std::map<std::string, int64_t>& summary)
118 {
119 auto engine = EngineHelper::GetCurrentEngine();
120 CHECK_NULL_RETURN(engine, nullptr);
121 NativeEngine* nativeEngine = engine->GetNativeEngine();
122 napi_env env = reinterpret_cast<napi_env>(nativeEngine);
123 std::shared_ptr<UDMF::Summary> udmfSummary = std::make_shared<UDMF::Summary>();
124 CHECK_NULL_RETURN(udmfSummary, nullptr);
125 udmfSummary->totalSize = 0;
126 for (auto element : summary) {
127 udmfSummary->totalSize += element.second;
128 }
129 udmfSummary->summary = std::move(summary);
130 napi_value dataVal = nullptr;
131 UDMF::SummaryNapi::NewInstance(env, udmfSummary, dataVal);
132 CHECK_NULL_RETURN(dataVal, nullptr);
133 return dataVal;
134 }
135
SetData(const RefPtr<UnifiedData> & unifiedData,std::string & key)136 int32_t UdmfClientImpl::SetData(const RefPtr<UnifiedData>& unifiedData, std::string& key)
137 {
138 auto& client = UDMF::UdmfClient::GetInstance();
139 UDMF::CustomOption udCustomOption;
140 udCustomOption.intention = UDMF::Intention::UD_INTENTION_DRAG;
141 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
142 CHECK_NULL_RETURN(udData, UDMF::E_ERROR);
143 int32_t ret = client.SetData(udCustomOption, *udData->GetUnifiedData(), key);
144 return ret;
145 }
146
GetData(const RefPtr<UnifiedData> & unifiedData,const std::string & key)147 int32_t UdmfClientImpl::GetData(const RefPtr<UnifiedData>& unifiedData, const std::string& key)
148 {
149 auto& client = UDMF::UdmfClient::GetInstance();
150 UDMF::QueryOption queryOption;
151 queryOption.key = key;
152 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
153 CHECK_NULL_RETURN(udData, UDMF::E_ERROR);
154 int ret = client.GetData(queryOption, *udData->GetUnifiedData());
155 return ret;
156 }
157
StartAsyncDataRetrieval(napi_env env,napi_value napiValue,const std::string & key)158 int32_t UdmfClientImpl::StartAsyncDataRetrieval(napi_env env, napi_value napiValue, const std::string& key)
159 {
160 UDMF::GetDataParams getDataParams;
161 getDataParams.query.key = key;
162 getDataParams.query.intention = UDMF::Intention::UD_INTENTION_DRAG;
163 auto status = UDMF::GetDataParamsNapi::Convert2NativeValue(env, napiValue, getDataParams, key);
164 if (!status) {
165 return -1;
166 }
167 return static_cast<int32_t>(UDMF::UdmfAsyncClient::GetInstance().StartAsyncDataRetrieval(getDataParams));
168 }
169
Cancel(const std::string & key)170 int32_t UdmfClientImpl::Cancel(const std::string& key)
171 {
172 return static_cast<int32_t>(UDMF::UdmfAsyncClient::GetInstance().Cancel(key));
173 }
174
GetSummary(std::string & key,std::map<std::string,int64_t> & summaryMap)175 int32_t UdmfClientImpl::GetSummary(std::string& key, std::map<std::string, int64_t>& summaryMap)
176 {
177 auto& client = UDMF::UdmfClient::GetInstance();
178 UDMF::Summary summary;
179 UDMF::QueryOption queryOption;
180 queryOption.key = key;
181 int32_t ret = client.GetSummary(queryOption, summary);
182 summaryMap = summary.summary;
183 return ret;
184 }
185
GetRemoteStatus(std::string & key)186 bool UdmfClientImpl::GetRemoteStatus(std::string& key)
187 {
188 auto& client = UDMF::UdmfClient::GetInstance();
189 bool isRemoteData = false;
190 UDMF::QueryOption queryOption;
191 queryOption.key = key;
192 int32_t ret = client.IsRemoteData(queryOption, isRemoteData);
193 if (ret != 0) {
194 // if ret is not 0, udmf client has not been sync, so return true to use remote getData.
195 return true;
196 }
197 return isRemoteData;
198 }
199
GetSize()200 int64_t UnifiedDataImpl::GetSize()
201 {
202 CHECK_NULL_RETURN(unifiedData_, 0);
203 return unifiedData_->GetRecords().size();
204 }
205
GetUnifiedData()206 std::shared_ptr<UDMF::UnifiedData> UnifiedDataImpl::GetUnifiedData()
207 {
208 if (unifiedData_ == nullptr) {
209 unifiedData_ = std::make_shared<UDMF::UnifiedData>();
210 }
211 return unifiedData_;
212 }
213
SetUnifiedData(std::shared_ptr<UDMF::UnifiedData> unifiedData)214 void UnifiedDataImpl::SetUnifiedData(std::shared_ptr<UDMF::UnifiedData> unifiedData)
215 {
216 unifiedData_ = unifiedData;
217 }
218
AddFormRecord(const RefPtr<UnifiedData> & unifiedData,int32_t formId,const RequestFormInfo & cardInfo)219 void UdmfClientImpl::AddFormRecord(
220 const RefPtr<UnifiedData>& unifiedData, int32_t formId, const RequestFormInfo& cardInfo)
221 {
222 auto formRecord = std::make_shared<UDMF::SystemDefinedForm>();
223 formRecord->SetFormId(formId);
224 formRecord->SetFormName(cardInfo.cardName);
225 formRecord->SetBundleName(cardInfo.bundleName);
226 formRecord->SetAbilityName(cardInfo.abilityName);
227 formRecord->SetModule(cardInfo.moduleName);
228 formRecord->SetType(UDMF::UDType::SYSTEM_DEFINED_FORM);
229
230 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
231 CHECK_NULL_VOID(udData);
232 CHECK_NULL_VOID(udData->GetUnifiedData());
233 udData->GetUnifiedData()->AddRecord(formRecord);
234 }
235
AddLinkRecord(const RefPtr<UnifiedData> & unifiedData,const std::string & url,const std::string & description)236 void UdmfClientImpl::AddLinkRecord(
237 const RefPtr<UnifiedData>& unifiedData, const std::string& url, const std::string& description)
238 {
239 auto record = std::make_shared<UDMF::Link>(url, description);
240
241 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
242 CHECK_NULL_VOID(udData);
243 CHECK_NULL_VOID(udData->GetUnifiedData());
244 udData->GetUnifiedData()->AddRecord(record);
245 }
246
GetLinkRecord(const RefPtr<UnifiedData> & unifiedData,std::string & url,std::string & description)247 void UdmfClientImpl::GetLinkRecord(
248 const RefPtr<UnifiedData>& unifiedData, std::string& url, std::string& description)
249 {
250 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
251 CHECK_NULL_VOID(udData);
252 CHECK_NULL_VOID(udData->GetUnifiedData());
253 auto records = udData->GetUnifiedData()->GetRecords();
254 for (auto record : records) {
255 UDMF::UDType type = record->GetType();
256 if (type == UDMF::UDType::HYPERLINK) {
257 UDMF::Link* link = reinterpret_cast<UDMF::Link*>(record.get());
258 url = link->GetUrl();
259 description = link->GetDescription();
260 return;
261 }
262 }
263 }
264
AddHtmlRecord(const RefPtr<UnifiedData> & unifiedData,const std::string & htmlContent,const std::string & plainContent)265 void UdmfClientImpl::AddHtmlRecord(
266 const RefPtr<UnifiedData>& unifiedData, const std::string& htmlContent, const std::string& plainContent)
267 {
268 auto htmlRecord = std::make_shared<UDMF::Html>(htmlContent, plainContent);
269
270 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
271 CHECK_NULL_VOID(udData);
272 CHECK_NULL_VOID(udData->GetUnifiedData());
273 if (!plainContent.empty() || !htmlContent.empty()) {
274 udData->GetUnifiedData()->AddRecord(htmlRecord);
275 }
276 }
277
GetHtmlRecord(const RefPtr<UnifiedData> & unifiedData,std::string & htmlContent,std::string & plainContent)278 void UdmfClientImpl::GetHtmlRecord(
279 const RefPtr<UnifiedData>& unifiedData, std::string& htmlContent, std::string& plainContent)
280 {
281 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
282 CHECK_NULL_VOID(udData);
283 CHECK_NULL_VOID(udData->GetUnifiedData());
284 auto records = udData->GetUnifiedData()->GetRecords();
285 for (auto record : records) {
286 UDMF::UDType type = record->GetType();
287 if (type == UDMF::UDType::HTML) {
288 UDMF::Html* html = reinterpret_cast<UDMF::Html*>(record.get());
289 plainContent = html->GetPlainContent();
290 htmlContent = html->GetHtmlContent();
291 return;
292 }
293 }
294 }
295
AddPixelMapRecord(const RefPtr<UnifiedData> & unifiedData,std::vector<uint8_t> & data,PixelMapRecordDetails & details)296 void UdmfClientImpl::AddPixelMapRecord(const RefPtr<UnifiedData>& unifiedData, std::vector<uint8_t>& data,
297 PixelMapRecordDetails& details)
298 {
299 auto record = std::make_shared<UDMF::SystemDefinedPixelMap>(data);
300 UDMF::UDDetails uDetails = {
301 { "width", details.width },
302 { "height", details.height },
303 { "pixel-format", static_cast<int32_t>(details.pixelFormat) },
304 { "alpha-type", static_cast<int32_t>(details.alphaType) } };
305 record->SetDetails(uDetails);
306 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
307 CHECK_NULL_VOID(udData);
308 CHECK_NULL_VOID(udData->GetUnifiedData());
309 udData->GetUnifiedData()->AddRecord(record);
310 }
311
AddImageRecord(const RefPtr<UnifiedData> & unifiedData,const std::string & uri)312 void UdmfClientImpl::AddImageRecord(const RefPtr<UnifiedData>& unifiedData, const std::string& uri)
313 {
314 auto record = std::make_shared<UDMF::Image>(uri);
315
316 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
317 CHECK_NULL_VOID(udData);
318 CHECK_NULL_VOID(udData->GetUnifiedData());
319 udData->GetUnifiedData()->AddRecord(record);
320 }
321
AddPlainTextRecord(const RefPtr<UnifiedData> & unifiedData,const std::string & selectedStr)322 void UdmfClientImpl::AddPlainTextRecord(const RefPtr<UnifiedData>& unifiedData, const std::string& selectedStr)
323 {
324 auto record = std::make_shared<UDMF::PlainText>(selectedStr, "");
325
326 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
327 CHECK_NULL_VOID(udData);
328 CHECK_NULL_VOID(udData->GetUnifiedData());
329 udData->GetUnifiedData()->AddRecord(record);
330 }
331
GetSinglePlainTextRecord(const RefPtr<UnifiedData> & unifiedData)332 std::string UdmfClientImpl::GetSinglePlainTextRecord(const RefPtr<UnifiedData>& unifiedData)
333 {
334 std::string str = "";
335 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
336 CHECK_NULL_RETURN(udData, str);
337 CHECK_NULL_RETURN(udData->GetUnifiedData(), str);
338 auto records = udData->GetUnifiedData()->GetRecords();
339 if (records.size() >= 1 && records[0]->GetType() == UDMF::UDType::PLAIN_TEXT) {
340 UDMF::PlainText* plainText = reinterpret_cast<UDMF::PlainText*>(records[0].get());
341 str = plainText->GetContent();
342 }
343 return str;
344 }
345
AddFileUriRecord(const RefPtr<UnifiedData> & unifiedData,std::vector<std::string> & uri)346 bool UdmfClientImpl::AddFileUriRecord(const RefPtr<UnifiedData>& unifiedData, std::vector<std::string>& uri)
347 {
348 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
349 CHECK_NULL_RETURN(udData, false);
350 CHECK_NULL_RETURN(udData->GetUnifiedData(), false);
351
352 for (std::string u : uri) {
353 LOGI("DragDrop event AddFileUriRecord, uri:%{public}s", u.c_str());
354 auto record = std::make_shared<UDMF::Image>(u);
355 udData->GetUnifiedData()->AddRecord(record);
356 }
357
358 return true;
359 }
360
GetFileUriRecord(const RefPtr<UnifiedData> & unifiedData,std::vector<std::string> & uri)361 bool UdmfClientImpl::GetFileUriRecord(const RefPtr<UnifiedData>& unifiedData, std::vector<std::string>& uri)
362 {
363 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
364 CHECK_NULL_RETURN(udData, false);
365 CHECK_NULL_RETURN(udData->GetUnifiedData(), false);
366 auto records = udData->GetUnifiedData()->GetRecords();
367
368 for (auto record : records) {
369 UDMF::UDType type = record->GetType();
370 if (type == UDMF::UDType::IMAGE || type == UDMF::UDType::AUDIO ||
371 type == UDMF::UDType::VIDEO || type == UDMF::UDType::FILE) {
372 UDMF::File* file = reinterpret_cast<UDMF::File*>(record.get());
373 if (file) {
374 uri.emplace_back(file->GetUri());
375 LOGI("DragDrop event GetFileUri, uri:%{public}s", file->GetUri().c_str());
376 } else {
377 LOGE("DragDrop event GetFileUri file is null");
378 }
379 }
380 }
381 return true;
382 }
383
GetPlainTextRecords(const RefPtr<UnifiedData> & unifiedData)384 std::vector<std::string> UdmfClientImpl::GetPlainTextRecords(const RefPtr<UnifiedData>& unifiedData)
385 {
386 std::vector<std::string> textRecords;
387 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
388 CHECK_NULL_RETURN(udData, textRecords);
389 CHECK_NULL_RETURN(udData->GetUnifiedData(), textRecords);
390 auto records = udData->GetUnifiedData()->GetRecords();
391 for (const auto& record : records) {
392 UDMF::UDType type = record->GetType();
393 if (type == UDMF::UDType::PLAIN_TEXT) {
394 UDMF::PlainText* plainText = reinterpret_cast<UDMF::PlainText*>(record.get());
395 std::string str = plainText->GetContent();
396 textRecords.emplace_back(str);
397 }
398 }
399 return textRecords;
400 }
401
GetVideoRecordUri(const RefPtr<UnifiedData> & unifiedData,std::string & uri)402 int32_t UdmfClientImpl::GetVideoRecordUri(const RefPtr<UnifiedData>& unifiedData, std::string& uri)
403 {
404 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
405 CHECK_NULL_RETURN(udData, UDMF::E_ERROR);
406 CHECK_NULL_RETURN(udData->GetUnifiedData(), UDMF::E_ERROR);
407 auto records = udData->GetUnifiedData()->GetRecords();
408 if (records.size() == 0) {
409 return UDMF::E_ERROR;
410 }
411 auto video = static_cast<UDMF::Video*>(records[0].get());
412 uri = video->GetUri();
413 return 0;
414 }
415
GetErrorInfo(int32_t errorCode)416 std::pair<int32_t, std::string> UdmfClientImpl::GetErrorInfo(int32_t errorCode)
417 {
418 switch (errorCode) {
419 case UDMF::E_NOT_FOUND:
420 return { ERROR_CODE_DRAG_DATA_NOT_FOUND, "GetData failed, data not found." };
421 default:
422 return { ERROR_CODE_DRAG_DATA_ERROR, "GetData failed, data error." };
423 }
424 }
425
AddSpanStringRecord(const RefPtr<UnifiedData> & unifiedData,std::vector<uint8_t> & data)426 void UdmfClientImpl::AddSpanStringRecord(
427 const RefPtr<UnifiedData>& unifiedData, std::vector<uint8_t>& data)
428 {
429 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
430 CHECK_NULL_VOID(udData);
431 CHECK_NULL_VOID(udData->GetUnifiedData());
432 auto record = std::make_shared<UDMF::ApplicationDefinedRecord>("OPENHARMONY_STYLED_STRING_UDMF", data);
433 udData->GetUnifiedData()->AddRecord(record);
434 }
435
GetSpanStringRecord(const RefPtr<UnifiedData> & unifiedData)436 std::vector<uint8_t> UdmfClientImpl::GetSpanStringRecord(const RefPtr<UnifiedData>& unifiedData)
437 {
438 std::vector<uint8_t> arr;
439 auto udData = AceType::DynamicCast<UnifiedDataImpl>(unifiedData);
440 CHECK_NULL_RETURN(udData, arr);
441 CHECK_NULL_RETURN(udData->GetUnifiedData(), arr);
442 auto records = udData->GetUnifiedData()->GetRecords();
443 for (auto record: records) {
444 UDMF::UDType type = record->GetType();
445 if (type == UDMF::UDType::APPLICATION_DEFINED_RECORD) {
446 UDMF::ApplicationDefinedRecord* app = reinterpret_cast<UDMF::ApplicationDefinedRecord*>(record.get());
447 if (app->GetApplicationDefinedType() == "OPENHARMONY_STYLED_STRING_UDMF") {
448 arr = app->GetRawData();
449 return arr;
450 }
451 }
452 }
453 return arr;
454 }
455 } // namespace OHOS::Ace
456