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