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