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 = OHOS::sptr<PasteboardObserverCapiImpl>::MakeSptr();
129 if (observerBox == nullptr) {
130 return ERR_INNER_ERROR;
131 }
132 observerBox->SetInnerObserver(observer);
133 observerBox->SetType(static_cast<Pasteboard_NotifyType>(type));
134 bool ret = PasteboardClient::GetInstance()->Subscribe(static_cast<PasteboardObserverType>(type), observerBox);
135 PASTEBOARD_CHECK_AND_RETURN_RET_LOGE(ret, ERR_OK, PASTEBOARD_MODULE_CAPI, "subscribe observer failed");
136 pasteboard->observers_[observer] = observerBox;
137 return ERR_OK;
138 }
139
OH_Pasteboard_Unsubscribe(OH_Pasteboard * pasteboard,int type,const OH_PasteboardObserver * observer)140 int OH_Pasteboard_Unsubscribe(OH_Pasteboard *pasteboard, int type, const OH_PasteboardObserver *observer)
141 {
142 if (!IsPasteboardValid(pasteboard) || observer == nullptr || type < NOTIFY_LOCAL_DATA_CHANGE ||
143 type > NOTIFY_REMOTE_DATA_CHANGE) {
144 return ERR_INVALID_PARAMETER;
145 }
146 std::lock_guard<std::mutex> lock(pasteboard->mutex);
147 auto iter = pasteboard->observers_.find(observer);
148 if (iter == pasteboard->observers_.end()) {
149 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "couldn't find this observer");
150 return ERR_OK;
151 }
152 PasteboardClient::GetInstance()->Unsubscribe(static_cast<PasteboardObserverType>(type), iter->second);
153 pasteboard->observers_.erase(iter);
154 return ERR_OK;
155 }
156
OH_Pasteboard_GetChangeCount(OH_Pasteboard * pasteboard)157 uint32_t OH_Pasteboard_GetChangeCount(OH_Pasteboard *pasteboard)
158 {
159 uint32_t changeCount = 0;
160 PasteboardClient::GetInstance()->GetChangeCount(changeCount);
161 return changeCount;
162 }
163
OH_Pasteboard_IsRemoteData(OH_Pasteboard * pasteboard)164 bool OH_Pasteboard_IsRemoteData(OH_Pasteboard *pasteboard)
165 {
166 return PasteboardClient::GetInstance()->IsRemoteData();
167 }
168
OH_Pasteboard_GetDataSource(OH_Pasteboard * pasteboard,char * source,unsigned int len)169 int OH_Pasteboard_GetDataSource(OH_Pasteboard *pasteboard, char *source, unsigned int len)
170 {
171 if (!IsPasteboardValid(pasteboard) || source == nullptr || len == 0) {
172 return ERR_INVALID_PARAMETER;
173 }
174 std::string bundleName;
175 auto ret = PasteboardClient::GetInstance()->GetDataSource(bundleName);
176 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
177 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "client getDataSource return invalid, result is %{public}d", ret);
178 return GetMappedCode(ret);
179 }
180 if (strcpy_s(source, len, bundleName.c_str()) != EOK) {
181 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "copy string fail");
182 return ERR_INNER_ERROR;
183 }
184 return ERR_OK;
185 }
186
OH_Pasteboard_GetMimeTypes(OH_Pasteboard * pasteboard,unsigned int * count)187 char **OH_Pasteboard_GetMimeTypes(OH_Pasteboard *pasteboard, unsigned int *count)
188 {
189 if (!IsPasteboardValid(pasteboard) || count == nullptr) {
190 return nullptr;
191 }
192 std::lock_guard<std::mutex> lock(pasteboard->mutex);
193 pasteboard->mimeTypes_ = PasteboardClient::GetInstance()->GetMimeTypes();
194 unsigned int typeNum = pasteboard->mimeTypes_.size();
195 if (typeNum == 0 || typeNum > MAX_MIMETYPES_NUM) {
196 *count = 0;
197 return nullptr;
198 }
199 *count = typeNum;
200 delete[] pasteboard->mimeTypesPtr;
201 pasteboard->mimeTypesPtr = new char *[typeNum];
202 for (unsigned int i = 0; i < typeNum; ++i) {
203 pasteboard->mimeTypesPtr[i] = const_cast<char*>(pasteboard->mimeTypes_[i].c_str());
204 }
205 return pasteboard->mimeTypesPtr;
206 }
207
OH_Pasteboard_HasType(OH_Pasteboard * pasteboard,const char * type)208 bool OH_Pasteboard_HasType(OH_Pasteboard *pasteboard, const char *type)
209 {
210 if (!IsPasteboardValid(pasteboard) || type == nullptr) {
211 return false;
212 }
213 return PasteboardClient::GetInstance()->HasDataType(std::string(type));
214 }
215
OH_Pasteboard_HasData(OH_Pasteboard * pasteboard)216 bool OH_Pasteboard_HasData(OH_Pasteboard *pasteboard)
217 {
218 if (!IsPasteboardValid(pasteboard)) {
219 return false;
220 }
221 return PasteboardClient::GetInstance()->HasPasteData();
222 }
223
OH_Pasteboard_GetData(OH_Pasteboard * pasteboard,int * status)224 OH_UdmfData *OH_Pasteboard_GetData(OH_Pasteboard *pasteboard, int *status)
225 {
226 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "enter");
227 if (!IsPasteboardValid(pasteboard) || status == nullptr) {
228 return nullptr;
229 }
230 auto unifiedData = std::make_shared<OHOS::UDMF::UnifiedData>();
231 int32_t ret = PasteboardClient::GetInstance()->GetUdsdData(*unifiedData);
232 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
233 PASTEBOARD_HILOGE(
234 PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_GetData return invalid, result is %{public}d", ret);
235 *status = GetMappedCode(ret);
236 return nullptr;
237 }
238 OH_UdmfData *data = OH_UdmfData_Create();
239 if (data == nullptr) {
240 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "Failed to create OH_UdmfData");
241 *status = ERR_PASTEBOARD_GET_DATA_FAILED;
242 return nullptr;
243 }
244 data->unifiedData_ = std::move(unifiedData);
245 *status = ERR_OK;
246 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "leave");
247 return data;
248 }
249
OH_Pasteboard_GetDataParams_Create(void)250 Pasteboard_GetDataParams *OH_Pasteboard_GetDataParams_Create(void)
251 {
252 Pasteboard_GetDataParams *params = new (std::nothrow) Pasteboard_GetDataParams();
253 if (params == nullptr) {
254 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "new Pasteboard_GetDataParams failed!");
255 return nullptr;
256 }
257
258 params->destUri = new (std::nothrow) char[MAX_PATH_LEN] {0};
259 if (params->destUri == nullptr) {
260 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "malloc failed!");
261 delete params;
262 params = nullptr;
263 return nullptr;
264 }
265 return params;
266 }
267
OH_Pasteboard_GetDataParams_Destroy(Pasteboard_GetDataParams * params)268 void OH_Pasteboard_GetDataParams_Destroy(Pasteboard_GetDataParams* params)
269 {
270 if (params == nullptr) {
271 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
272 return;
273 }
274 if (params->destUri != nullptr) {
275 delete[] params->destUri;
276 params->destUri = nullptr;
277 }
278 delete params;
279 params = nullptr;
280 }
281
OH_Pasteboard_GetDataParams_SetProgressIndicator(Pasteboard_GetDataParams * params,Pasteboard_ProgressIndicator progressIndicator)282 void OH_Pasteboard_GetDataParams_SetProgressIndicator(Pasteboard_GetDataParams* params,
283 Pasteboard_ProgressIndicator progressIndicator)
284 {
285 if (params == nullptr) {
286 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
287 return;
288 }
289 params->progressIndicator = progressIndicator;
290 }
291
OH_Pasteboard_GetDataParams_SetDestUri(Pasteboard_GetDataParams * params,const char * destUri,uint32_t destUriLen)292 void OH_Pasteboard_GetDataParams_SetDestUri(Pasteboard_GetDataParams* params, const char* destUri, uint32_t destUriLen)
293 {
294 if (params == nullptr || params->destUri == nullptr || destUri == nullptr || destUriLen == 0 ||
295 destUriLen >= MAX_PATH_LEN) {
296 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
297 return;
298 }
299
300 params->destUriLen = destUriLen;
301 if (strcpy_s(params->destUri, MAX_PATH_LEN, destUri) != EOK) {
302 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "copy destUri failed!");
303 return;
304 }
305 }
306
OH_Pasteboard_GetDataParams_SetFileConflictOptions(Pasteboard_GetDataParams * params,Pasteboard_FileConflictOptions option)307 void OH_Pasteboard_GetDataParams_SetFileConflictOptions(Pasteboard_GetDataParams* params,
308 Pasteboard_FileConflictOptions option)
309 {
310 if (params == nullptr) {
311 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
312 return;
313 }
314 params->fileConflictOptions = option;
315 }
316
OH_Pasteboard_GetDataParams_SetProgressListener(Pasteboard_GetDataParams * params,const OH_Pasteboard_ProgressListener listener)317 void OH_Pasteboard_GetDataParams_SetProgressListener(Pasteboard_GetDataParams* params,
318 const OH_Pasteboard_ProgressListener listener)
319 {
320 if (params == nullptr) {
321 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "invalid params!");
322 return;
323 }
324 params->progressListener = listener;
325 }
326
OH_Pasteboard_ProgressInfo_GetProgress(Pasteboard_ProgressInfo * progressInfo)327 int OH_Pasteboard_ProgressInfo_GetProgress(Pasteboard_ProgressInfo* progressInfo)
328 {
329 if (progressInfo == nullptr) {
330 return ERR_INVALID_PARAMETER;
331 }
332 return progressInfo->progress;
333 }
334
ProgressNotify(std::shared_ptr<GetDataParams> params)335 void ProgressNotify(std::shared_ptr<GetDataParams> params)
336 {
337 if (params == nullptr || params->info == nullptr) {
338 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "Error: params or params->info is nullptr in ProgressNotify.");
339 return;
340 }
341 if (g_callback != nullptr) {
342 g_callback(reinterpret_cast<Pasteboard_ProgressInfo *>(params->info));
343 }
344 }
345
OH_Pasteboard_ProgressCancel(Pasteboard_GetDataParams * params)346 void OH_Pasteboard_ProgressCancel(Pasteboard_GetDataParams* params)
347 {
348 ProgressSignalClient::GetInstance().Cancel();
349 }
350
OH_Pasteboard_GetDataWithProgress(OH_Pasteboard * pasteboard,Pasteboard_GetDataParams * params,int * status)351 OH_UdmfData* OH_Pasteboard_GetDataWithProgress(OH_Pasteboard* pasteboard, Pasteboard_GetDataParams* params, int* status)
352 {
353 if (!IsPasteboardValid(pasteboard) || params == nullptr || status == nullptr) {
354 if (status != nullptr) {
355 *status = ERR_INVALID_PARAMETER;
356 }
357 return nullptr;
358 }
359 auto unifiedData = std::make_shared<OHOS::UDMF::UnifiedData>();
360 auto getDataParams = std::make_shared<OHOS::MiscServices::GetDataParams>();
361 size_t destLen = (params->destUri == nullptr) ? 0 : strlen(params->destUri);
362 if (destLen != 0) {
363 if (destLen > MAX_DESTURI_LEN || params->destUriLen == 0 || params->destUriLen > MAX_DESTURI_LEN ||
364 destLen != static_cast<size_t>(params->destUriLen)) {
365 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "destUri is invalid, destUriLen=%{public}zu", destLen);
366 *status = ERR_INVALID_PARAMETER;
367 return nullptr;
368 }
369 getDataParams->destUri = params->destUri;
370 }
371 g_callback = params->progressListener;
372 getDataParams->fileConflictOption = (FileConflictOption)params->fileConflictOptions;
373 getDataParams->progressIndicator = (ProgressIndicator)params->progressIndicator;
374 getDataParams->info = reinterpret_cast<ProgressInfo *>(¶ms->info);
375 struct ProgressListener listener = {
376 .ProgressNotify = ProgressNotify,
377 };
378 getDataParams->listener = listener;
379 int32_t ret = PasteboardClient::GetInstance()->GetUnifiedDataWithProgress(*unifiedData, getDataParams);
380 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
381 PASTEBOARD_HILOGE(
382 PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_GetDataWithProgress return invalid, result is %{public}d",
383 ret);
384 auto iter = errCodeMap.find(static_cast<PasteboardError>(ret));
385 if (iter != errCodeMap.end()) {
386 *status = iter->second;
387 } else {
388 *status = ERR_PASTEBOARD_GET_DATA_FAILED;
389 }
390 return nullptr;
391 }
392 OH_UdmfData *data = OH_UdmfData_Create();
393 if (data == nullptr) {
394 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "Failed to create OH_UdmfData");
395 *status = ERR_PASTEBOARD_GET_DATA_FAILED;
396 return nullptr;
397 }
398 data->unifiedData_ = std::move(unifiedData);
399 *status = ERR_OK;
400 return data;
401 }
402
OH_Pasteboard_SetData(OH_Pasteboard * pasteboard,OH_UdmfData * data)403 int OH_Pasteboard_SetData(OH_Pasteboard *pasteboard, OH_UdmfData *data)
404 {
405 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "enter");
406 if (!IsPasteboardValid(pasteboard) || data == nullptr) {
407 return ERR_INVALID_PARAMETER;
408 }
409 int32_t ret = PasteboardClient::GetInstance()->SetUdsdData(*(data->unifiedData_));
410 if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
411 PASTEBOARD_HILOGE(
412 PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_SetData return invalid, result is %{public}d", ret);
413 return GetMappedCode(ret);
414 }
415 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "leave");
416 return ERR_OK;
417 }
418
OH_Pasteboard_ClearData(OH_Pasteboard * pasteboard)419 int OH_Pasteboard_ClearData(OH_Pasteboard *pasteboard)
420 {
421 if (!IsPasteboardValid(pasteboard)) {
422 return ERR_INVALID_PARAMETER;
423 }
424 PasteboardClient::GetInstance()->Clear();
425 return ERR_OK;
426 } // namespace OHOS