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