1 /*
2 * Copyright (c) 2024 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 #define LOG_TAG "Pasteboard_Capi"
17
18 #include "oh_pasteboard_observer_impl.h"
19 #include "pasteboard_client.h"
20 #include "pasteboard_hilog.h"
21 #include "udmf_capi_common.h"
22
23 using namespace OHOS::MiscServices;
24
25 static OH_Pasteboard_ProgressListener g_callback = {0};
26 #define MAX_PATH_LEN 1024
27 #define MAX_DESTURI_LEN 250
28
IsPasteboardValid(OH_Pasteboard * pasteboard)29 static bool IsPasteboardValid(OH_Pasteboard *pasteboard)
30 {
31 return pasteboard != nullptr && pasteboard->cid == PASTEBOARD_STRUCT_ID;
32 }
33
IsSubscriberValid(OH_PasteboardObserver * observer)34 static bool IsSubscriberValid(OH_PasteboardObserver *observer)
35 {
36 return observer != nullptr && observer->cid == SUBSCRIBER_STRUCT_ID;
37 }
38
GetMappedCode(int32_t code)39 static PASTEBOARD_ErrCode GetMappedCode(int32_t code)
40 {
41 auto iter = errCodeMap.find(static_cast<PasteboardError>(code));
42 if (iter != errCodeMap.end()) {
43 return iter->second;
44 }
45 return ERR_INNER_ERROR;
46 }
47
OH_PasteboardObserver_Create()48 OH_PasteboardObserver *OH_PasteboardObserver_Create()
49 {
50 OH_PasteboardObserver *observer = new (std::nothrow) OH_PasteboardObserver();
51 if (observer == nullptr) {
52 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "allocate memory fail.");
53 return nullptr;
54 }
55 return observer;
56 }
57
OH_PasteboardObserver_Destroy(OH_PasteboardObserver * observer)58 int OH_PasteboardObserver_Destroy(OH_PasteboardObserver *observer)
59 {
60 if (!IsSubscriberValid(observer)) {
61 return ERR_INVALID_PARAMETER;
62 }
63 if (observer->finalize != nullptr) {
64 (observer->finalize)(observer->context);
65 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CAPI, "context finalized");
66 }
67 delete observer;
68 return ERR_OK;
69 }
70
OH_PasteboardObserver_SetData(OH_PasteboardObserver * observer,void * context,const Pasteboard_Notify callback,const Pasteboard_Finalize finalize)71 int OH_PasteboardObserver_SetData(OH_PasteboardObserver *observer, void *context, const Pasteboard_Notify callback,
72 const Pasteboard_Finalize finalize)
73 {
74 if (observer == nullptr || callback == nullptr) {
75 return ERR_INVALID_PARAMETER;
76 }
77 observer->callback = callback;
78 if (context != nullptr && finalize == nullptr) {
79 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "finalize is null");
80 return ERR_INVALID_PARAMETER;
81 }
82 observer->context = context;
83 observer->finalize = finalize;
84 return ERR_OK;
85 }
86
OH_Pasteboard_Create()87 OH_Pasteboard *OH_Pasteboard_Create()
88 {
89 OH_Pasteboard *pasteboard = new (std::nothrow) OH_Pasteboard();
90 if (pasteboard == nullptr) {
91 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "allocate memory fail.");
92 return nullptr;
93 }
94 return pasteboard;
95 }
96
OH_Pasteboard_Destroy(OH_Pasteboard * pasteboard)97 void OH_Pasteboard_Destroy(OH_Pasteboard *pasteboard)
98 {
99 if (!IsPasteboardValid(pasteboard)) {
100 return;
101 }
102 std::lock_guard<std::mutex> lock(pasteboard->mutex);
103 for (auto iter : pasteboard->observers_) {
104 if (iter.second != nullptr) {
105 PasteboardClient::GetInstance()->Unsubscribe(
106 static_cast<PasteboardObserverType>(iter.second->GetType()), iter.second);
107 }
108 }
109 pasteboard->observers_.clear();
110 pasteboard->mimeTypes_.clear();
111 delete[] pasteboard->mimeTypesPtr;
112 pasteboard->mimeTypesPtr = nullptr;
113 delete pasteboard;
114 }
115
OH_Pasteboard_Subscribe(OH_Pasteboard * pasteboard,int type,const OH_PasteboardObserver * observer)116 int OH_Pasteboard_Subscribe(OH_Pasteboard *pasteboard, int type, const OH_PasteboardObserver *observer)
117 {
118 if (!IsPasteboardValid(pasteboard) || observer == nullptr || type < NOTIFY_LOCAL_DATA_CHANGE ||
119 type > NOTIFY_REMOTE_DATA_CHANGE) {
120 return ERR_INVALID_PARAMETER;
121 }
122 std::lock_guard<std::mutex> lock(pasteboard->mutex);
123 auto iter = pasteboard->observers_.find(observer);
124 if (iter != pasteboard->observers_.end()) {
125 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "observer exist.");
126 return ERR_OK;
127 }
128 OHOS::sptr<PasteboardObserverCapiImpl> observerBox = new (std::nothrow) PasteboardObserverCapiImpl();
129 if (observerBox == nullptr) {
130 return ERR_INNER_ERROR;
131 }
132 observerBox->SetInnerObserver(observer);
133 observerBox->SetType(static_cast<Pasteboard_NotifyType>(type));
134 pasteboard->observers_[observer] = observerBox;
135 PasteboardClient::GetInstance()->Subscribe(static_cast<PasteboardObserverType>(type), observerBox);
136 return ERR_OK;
137 }
138
OH_Pasteboard_Unsubscribe(OH_Pasteboard * pasteboard,int type,const OH_PasteboardObserver * observer)139 int OH_Pasteboard_Unsubscribe(OH_Pasteboard *pasteboard, int type, const OH_PasteboardObserver *observer)
140 {
141 if (!IsPasteboardValid(pasteboard) || observer == nullptr || type < NOTIFY_LOCAL_DATA_CHANGE ||
142 type > NOTIFY_REMOTE_DATA_CHANGE) {
143 return ERR_INVALID_PARAMETER;
144 }
145 std::lock_guard<std::mutex> lock(pasteboard->mutex);
146 auto iter = pasteboard->observers_.find(observer);
147 if (iter == pasteboard->observers_.end()) {
148 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "couldn't find this observer");
149 return ERR_OK;
150 }
151 PasteboardClient::GetInstance()->Unsubscribe(static_cast<PasteboardObserverType>(type), iter->second);
152 pasteboard->observers_.erase(iter);
153 return ERR_OK;
154 }
155
OH_Pasteboard_GetChangeCount(OH_Pasteboard * pasteboard)156 uint32_t OH_Pasteboard_GetChangeCount(OH_Pasteboard *pasteboard)
157 {
158 uint32_t changeCount = 0;
159 PasteboardClient::GetInstance()->GetChangeCount(changeCount);
160 return changeCount;
161 }
162
OH_Pasteboard_IsRemoteData(OH_Pasteboard * pasteboard)163 bool OH_Pasteboard_IsRemoteData(OH_Pasteboard *pasteboard)
164 {
165 if (!IsPasteboardValid(pasteboard)) {
166 return ERR_INVALID_PARAMETER;
167 }
168 return PasteboardClient::GetInstance()->IsRemoteData();
169 }
170
OH_Pasteboard_GetDataSource(OH_Pasteboard * pasteboard,char * source,unsigned int len)171 int OH_Pasteboard_GetDataSource(OH_Pasteboard *pasteboard, char *source, unsigned int len)
172 {
173 if (!IsPasteboardValid(pasteboard) || source == nullptr || len == 0) {
174 return ERR_INVALID_PARAMETER;
175 }
176 std::string bundleName;
177 auto ret = PasteboardClient::GetInstance()->GetDataSource(bundleName);
178 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
179 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "client getDataSource return invalid, result is %{public}d", ret);
180 return GetMappedCode(ret);
181 }
182 if (strcpy_s(source, len, bundleName.c_str()) != EOK) {
183 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "copy string fail");
184 return ERR_INNER_ERROR;
185 }
186 return ERR_OK;
187 }
188
OH_Pasteboard_GetMimeTypes(OH_Pasteboard * pasteboard,unsigned int * count)189 char **OH_Pasteboard_GetMimeTypes(OH_Pasteboard *pasteboard, unsigned int *count)
190 {
191 if (!IsPasteboardValid(pasteboard) || count == nullptr) {
192 return nullptr;
193 }
194 std::lock_guard<std::mutex> lock(pasteboard->mutex);
195 pasteboard->mimeTypes_ = PasteboardClient::GetInstance()->GetMimeTypes();
196 unsigned int typeNum = pasteboard->mimeTypes_.size();
197 if (typeNum == 0 || typeNum > MAX_MIMETYPES_NUM) {
198 *count = 0;
199 return nullptr;
200 }
201 *count = typeNum;
202 delete[] pasteboard->mimeTypesPtr;
203 pasteboard->mimeTypesPtr = new char *[typeNum];
204 for (unsigned int i = 0; i < typeNum; ++i) {
205 pasteboard->mimeTypesPtr[i] = const_cast<char*>(pasteboard->mimeTypes_[i].c_str());
206 }
207 return pasteboard->mimeTypesPtr;
208 }
209
OH_Pasteboard_HasType(OH_Pasteboard * pasteboard,const char * type)210 bool OH_Pasteboard_HasType(OH_Pasteboard *pasteboard, const char *type)
211 {
212 if (!IsPasteboardValid(pasteboard) || type == nullptr) {
213 return false;
214 }
215 return PasteboardClient::GetInstance()->HasDataType(std::string(type));
216 }
217
OH_Pasteboard_HasData(OH_Pasteboard * pasteboard)218 bool OH_Pasteboard_HasData(OH_Pasteboard *pasteboard)
219 {
220 if (!IsPasteboardValid(pasteboard)) {
221 return false;
222 }
223 return PasteboardClient::GetInstance()->HasPasteData();
224 }
225
OH_Pasteboard_GetData(OH_Pasteboard * pasteboard,int * status)226 OH_UdmfData *OH_Pasteboard_GetData(OH_Pasteboard *pasteboard, int *status)
227 {
228 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "enter");
229 if (!IsPasteboardValid(pasteboard) || status == nullptr) {
230 return nullptr;
231 }
232 auto unifiedData = std::make_shared<OHOS::UDMF::UnifiedData>();
233 int32_t ret = PasteboardClient::GetInstance()->GetUdsdData(*unifiedData);
234 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
235 PASTEBOARD_HILOGE(
236 PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_GetData return invalid, result is %{public}d", ret);
237 *status = GetMappedCode(ret);
238 return nullptr;
239 }
240 OH_UdmfData *data = OH_UdmfData_Create();
241 if (data == nullptr) {
242 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "Failed to create OH_UdmfData");
243 *status = ERR_PASTEBOARD_GET_DATA_FAILED;
244 return nullptr;
245 }
246 data->unifiedData_ = std::move(unifiedData);
247 *status = ERR_OK;
248 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "leave");
249 return data;
250 }
251
OH_Pasteboard_GetDataParams_Create(void)252 Pasteboard_GetDataParams *OH_Pasteboard_GetDataParams_Create(void)
253 {
254 Pasteboard_GetDataParams *params = new (std::nothrow) Pasteboard_GetDataParams();
255 if (params == nullptr) {
256 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "new Pasteboard_GetDataParams failed!");
257 return nullptr;
258 }
259
260 params->destUri = new (std::nothrow) char[MAX_PATH_LEN] {0};
261 if (params->destUri == nullptr) {
262 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "malloc failed!");
263 delete params;
264 params = nullptr;
265 return nullptr;
266 }
267 return params;
268 }
269
OH_Pasteboard_GetDataParams_Destroy(Pasteboard_GetDataParams * params)270 void OH_Pasteboard_GetDataParams_Destroy(Pasteboard_GetDataParams* params)
271 {
272 if (params == nullptr) {
273 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
274 return;
275 }
276 if (params->destUri != nullptr) {
277 delete[] params->destUri;
278 params->destUri = nullptr;
279 }
280 delete params;
281 params = nullptr;
282 }
283
OH_Pasteboard_GetDataParams_SetProgressIndicator(Pasteboard_GetDataParams * params,Pasteboard_ProgressIndicator progressIndicator)284 void OH_Pasteboard_GetDataParams_SetProgressIndicator(Pasteboard_GetDataParams* params,
285 Pasteboard_ProgressIndicator progressIndicator)
286 {
287 if (params == nullptr) {
288 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
289 return;
290 }
291 params->progressIndicator = progressIndicator;
292 }
293
OH_Pasteboard_GetDataParams_SetDestUri(Pasteboard_GetDataParams * params,const char * destUri,uint32_t destUriLen)294 void OH_Pasteboard_GetDataParams_SetDestUri(Pasteboard_GetDataParams* params, const char* destUri, uint32_t destUriLen)
295 {
296 if (params == nullptr || params->destUri == nullptr || destUri == nullptr || destUriLen == 0 ||
297 destUriLen >= MAX_PATH_LEN) {
298 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
299 return;
300 }
301
302 params->destUriLen = destUriLen;
303 if (strcpy_s(params->destUri, MAX_PATH_LEN, destUri) != EOK) {
304 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "copy destUri failed!");
305 return;
306 }
307 }
308
OH_Pasteboard_GetDataParams_SetFileConflictOptions(Pasteboard_GetDataParams * params,Pasteboard_FileConflictOptions option)309 void OH_Pasteboard_GetDataParams_SetFileConflictOptions(Pasteboard_GetDataParams* params,
310 Pasteboard_FileConflictOptions option)
311 {
312 if (params == nullptr) {
313 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
314 return;
315 }
316 params->fileConflictOptions = option;
317 }
318
OH_Pasteboard_GetDataParams_SetProgressListener(Pasteboard_GetDataParams * params,const OH_Pasteboard_ProgressListener listener)319 void OH_Pasteboard_GetDataParams_SetProgressListener(Pasteboard_GetDataParams* params,
320 const OH_Pasteboard_ProgressListener listener)
321 {
322 if (params == nullptr) {
323 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
324 return;
325 }
326 params->progressListener = listener;
327 }
328
OH_Pasteboard_ProgressInfo_GetProgress(Pasteboard_ProgressInfo * progressInfo)329 int OH_Pasteboard_ProgressInfo_GetProgress(Pasteboard_ProgressInfo* progressInfo)
330 {
331 if (progressInfo == nullptr) {
332 return ERR_INVALID_PARAMETER;
333 }
334 return progressInfo->progress;
335 }
336
ProgressNotify(std::shared_ptr<GetDataParams> params)337 void ProgressNotify(std::shared_ptr<GetDataParams> params)
338 {
339 if (params == nullptr || params->info == nullptr) {
340 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "Error: params or params->info is nullptr in ProgressNotify.");
341 return;
342 }
343 if (g_callback != nullptr) {
344 g_callback(reinterpret_cast<Pasteboard_ProgressInfo *>(params->info));
345 }
346 }
347
OH_Pasteboard_ProgressCancel(Pasteboard_GetDataParams * params)348 void OH_Pasteboard_ProgressCancel(Pasteboard_GetDataParams* params)
349 {
350 ProgressSignalClient::GetInstance().Cancel();
351 }
352
OH_Pasteboard_GetDataWithProgress(OH_Pasteboard * pasteboard,Pasteboard_GetDataParams * params,int * status)353 OH_UdmfData* OH_Pasteboard_GetDataWithProgress(OH_Pasteboard* pasteboard, Pasteboard_GetDataParams* params, int* status)
354 {
355 if (!IsPasteboardValid(pasteboard) || params == nullptr || status == nullptr) {
356 if (status != nullptr) {
357 *status = ERR_INVALID_PARAMETER;
358 }
359 return nullptr;
360 }
361 auto unifiedData = std::make_shared<OHOS::UDMF::UnifiedData>();
362 auto getDataParams = std::make_shared<OHOS::MiscServices::GetDataParams>();
363 size_t destLen = (params->destUri == nullptr) ? 0 : strlen(params->destUri);
364 if (destLen != 0) {
365 if (destLen > MAX_DESTURI_LEN || params->destUriLen == 0 || params->destUriLen > MAX_DESTURI_LEN ||
366 destLen != static_cast<size_t>(params->destUriLen)) {
367 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "destUri is invalid, destUriLen=%{public}zu", destLen);
368 *status = ERR_INVALID_PARAMETER;
369 return nullptr;
370 }
371 getDataParams->destUri = params->destUri;
372 }
373 g_callback = params->progressListener;
374 getDataParams->fileConflictOption = (FileConflictOption)params->fileConflictOptions;
375 getDataParams->progressIndicator = (ProgressIndicator)params->progressIndicator;
376 getDataParams->info = reinterpret_cast<ProgressInfo *>(¶ms->info);
377 struct ProgressListener listener = {
378 .ProgressNotify = ProgressNotify,
379 };
380 getDataParams->listener = listener;
381 int32_t ret = PasteboardClient::GetInstance()->GetUnifiedDataWithProgress(*unifiedData, getDataParams);
382 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
383 PASTEBOARD_HILOGE(
384 PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_GetDataWithProgress return invalid, result is %{public}d",
385 ret);
386 auto iter = errCodeMap.find(static_cast<PasteboardError>(ret));
387 if (iter != errCodeMap.end()) {
388 *status = iter->second;
389 } else {
390 *status = ERR_PASTEBOARD_GET_DATA_FAILED;
391 }
392 return nullptr;
393 }
394 OH_UdmfData *data = OH_UdmfData_Create();
395 if (data == nullptr) {
396 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "Failed to create OH_UdmfData");
397 *status = ERR_PASTEBOARD_GET_DATA_FAILED;
398 return nullptr;
399 }
400 data->unifiedData_ = std::move(unifiedData);
401 *status = ERR_OK;
402 return data;
403 }
404
OH_Pasteboard_SetData(OH_Pasteboard * pasteboard,OH_UdmfData * data)405 int OH_Pasteboard_SetData(OH_Pasteboard *pasteboard, OH_UdmfData *data)
406 {
407 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "enter");
408 if (!IsPasteboardValid(pasteboard) || data == nullptr) {
409 return ERR_INVALID_PARAMETER;
410 }
411 int32_t ret = PasteboardClient::GetInstance()->SetUdsdData(*(data->unifiedData_));
412 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
413 PASTEBOARD_HILOGE(
414 PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_SetData return invalid, result is %{public}d", ret);
415 return GetMappedCode(ret);
416 }
417 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "leave");
418 return ERR_OK;
419 }
420
OH_Pasteboard_ClearData(OH_Pasteboard * pasteboard)421 int OH_Pasteboard_ClearData(OH_Pasteboard *pasteboard)
422 {
423 if (!IsPasteboardValid(pasteboard)) {
424 return ERR_INVALID_PARAMETER;
425 }
426 PasteboardClient::GetInstance()->Clear();
427 return ERR_OK;
428 } // namespace OHOS