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.h"
19 #include <string>
20 #include <memory>
21 #include <thread>
22 #include <map>
23 #include "udmf.h"
24 #include "oh_pasteboard_err_code.h"
25 #include "oh_pasteboard_observer_impl.h"
26 #include "pasteboard_client.h"
27 #include "pasteboard_hilog.h"
28 #include "pasteboard_error.h"
29 #include "udmf_capi_common.h"
30 #include "i_pasteboard_observer.h"
31 
32 using namespace OHOS::MiscServices;
IsPasteboardValid(OH_Pasteboard * pasteboard)33 static bool IsPasteboardValid(OH_Pasteboard* pasteboard)
34 {
35     return pasteboard != nullptr && pasteboard->cid == PASTEBOARD_STRUCT_ID;
36 }
37 
IsSubscriberValid(OH_PasteboardObserver * observer)38 static bool IsSubscriberValid(OH_PasteboardObserver* observer)
39 {
40     return observer != nullptr && observer->cid == SUBSCRIBER_STRUCT_ID;
41 }
42 
GetMappedCode(int32_t code)43 static PASTEBOARD_ErrCode GetMappedCode(int32_t code)
44 {
45     auto iter = errCodeMap.find(static_cast<PasteboardError>(code));
46     if (iter != errCodeMap.end()) {
47         return iter->second;
48     }
49     return ERR_INNER_ERROR;
50 }
51 
OH_PasteboardObserver_Create()52 OH_PasteboardObserver* OH_PasteboardObserver_Create()
53 {
54     OH_PasteboardObserver* observer = new(std::nothrow) OH_PasteboardObserver();
55     if (observer == nullptr) {
56         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "allocate memory fail.");
57         return nullptr;
58     }
59     return observer;
60 }
61 
OH_PasteboardObserver_Destroy(OH_PasteboardObserver * observer)62 int OH_PasteboardObserver_Destroy(OH_PasteboardObserver* observer)
63 {
64     if (!IsSubscriberValid(observer)) {
65         return ERR_INVALID_PARAMETER;
66     }
67     if (observer->finalize != nullptr) {
68         (observer->finalize)(observer->context);
69         PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CAPI, "context finalized");
70     }
71     delete observer;
72     return ERR_OK;
73 }
74 
OH_PasteboardObserver_SetData(OH_PasteboardObserver * observer,void * context,const Pasteboard_Notify callback,const Pasteboard_Finalize finalize)75 int OH_PasteboardObserver_SetData(OH_PasteboardObserver* observer, void* context,
76     const Pasteboard_Notify callback, const Pasteboard_Finalize finalize)
77 {
78     if (observer == nullptr || callback == nullptr) {
79         return ERR_INVALID_PARAMETER;
80     }
81     observer->callback = callback;
82     if (context != nullptr && finalize == nullptr) {
83         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "finalize is null");
84         return ERR_INVALID_PARAMETER;
85     }
86     observer->context = context;
87     observer->finalize = finalize;
88     return ERR_OK;
89 }
90 
OH_Pasteboard_Create()91 OH_Pasteboard* OH_Pasteboard_Create()
92 {
93     OH_Pasteboard* pasteboard = new (std::nothrow) OH_Pasteboard();
94     if (pasteboard == nullptr) {
95         PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CAPI, "allocate memory fail.");
96         return nullptr;
97     }
98     return pasteboard;
99 }
100 
OH_Pasteboard_Destroy(OH_Pasteboard * pasteboard)101 void OH_Pasteboard_Destroy(OH_Pasteboard* pasteboard)
102 {
103     if (!IsPasteboardValid(pasteboard)) {
104         return;
105     }
106     std::lock_guard<std::mutex> lock(pasteboard->mutex);
107     for (auto iter : pasteboard->observers_) {
108         if (iter.second != nullptr) {
109             PasteboardClient::GetInstance()->Unsubscribe(
110                 static_cast<PasteboardObserverType>(iter.second->GetType()), iter.second);
111         }
112     }
113     pasteboard->observers_.clear();
114     pasteboard->mimeTypes_.clear();
115     delete[] pasteboard->mimeTypesPtr;
116     pasteboard->mimeTypesPtr = nullptr;
117     delete pasteboard;
118 }
119 
OH_Pasteboard_Subscribe(OH_Pasteboard * pasteboard,int type,const OH_PasteboardObserver * observer)120 int OH_Pasteboard_Subscribe(OH_Pasteboard* pasteboard, int type, const OH_PasteboardObserver* observer)
121 {
122     if (!IsPasteboardValid(pasteboard) || observer == nullptr || type < NOTIFY_LOCAL_DATA_CHANGE
123         || type > NOTIFY_REMOTE_DATA_CHANGE) {
124         return ERR_INVALID_PARAMETER;
125     }
126     std::lock_guard<std::mutex> lock(pasteboard->mutex);
127     auto iter = pasteboard->observers_.find(observer);
128     if (iter != pasteboard->observers_.end()) {
129         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "observer exist.");
130         return ERR_OK;
131     }
132     OHOS::sptr<PasteboardObserverCapiImpl> observerBox = new (std::nothrow) PasteboardObserverCapiImpl();
133     if (observerBox == nullptr) {
134         return ERR_INNER_ERROR;
135     }
136     observerBox->SetInnerObserver(observer);
137     observerBox->SetType(static_cast<Pasteboard_NotifyType>(type));
138     pasteboard->observers_[observer] = observerBox;
139     PasteboardClient::GetInstance()->Subscribe(static_cast<PasteboardObserverType>(type), observerBox);
140     return ERR_OK;
141 }
142 
OH_Pasteboard_Unsubscribe(OH_Pasteboard * pasteboard,int type,const OH_PasteboardObserver * observer)143 int OH_Pasteboard_Unsubscribe(OH_Pasteboard* pasteboard, int type, const OH_PasteboardObserver* observer)
144 {
145     if (!IsPasteboardValid(pasteboard) || observer == nullptr  || type < NOTIFY_LOCAL_DATA_CHANGE
146         || type > NOTIFY_REMOTE_DATA_CHANGE) {
147         return ERR_INVALID_PARAMETER;
148     }
149     std::lock_guard<std::mutex> lock(pasteboard->mutex);
150     auto iter = pasteboard->observers_.find(observer);
151     if (iter == pasteboard->observers_.end()) {
152         PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CAPI, "couldn't find this observer");
153         return ERR_OK;
154     }
155     PasteboardClient::GetInstance()->Unsubscribe(static_cast<PasteboardObserverType>(type), iter->second);
156     pasteboard->observers_.erase(iter);
157     return ERR_OK;
158 }
159 
OH_Pasteboard_IsRemoteData(OH_Pasteboard * pasteboard)160 bool OH_Pasteboard_IsRemoteData(OH_Pasteboard* pasteboard)
161 {
162     if (!IsPasteboardValid(pasteboard)) {
163         return ERR_INVALID_PARAMETER;
164     }
165     return PasteboardClient::GetInstance()->IsRemoteData();
166 }
167 
OH_Pasteboard_GetDataSource(OH_Pasteboard * pasteboard,char * source,unsigned int len)168 int OH_Pasteboard_GetDataSource(OH_Pasteboard* pasteboard, char* source, unsigned int len)
169 {
170     if (!IsPasteboardValid(pasteboard) || source == nullptr || len == 0) {
171         return ERR_INVALID_PARAMETER;
172     }
173     std::string bundleName;
174     auto ret = PasteboardClient::GetInstance()->GetDataSource(bundleName);
175     if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
176         PASTEBOARD_HILOGE(
177             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 ERR_INVALID_PARAMETER;
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 ERR_INVALID_PARAMETER;
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     if (!IsPasteboardValid(pasteboard) || status == nullptr) {
227         return nullptr;
228     }
229     auto unifiedData = std::make_shared<OHOS::UDMF::UnifiedData>();
230     int32_t ret = PasteboardClient::GetInstance()->GetUdsdData(*unifiedData);
231     if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
232         PASTEBOARD_HILOGE(
233             PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_GetData return invalid, result is %{public}d", ret);
234         *status = GetMappedCode(ret);
235         return nullptr;
236     }
237     OH_UdmfData* data = OH_UdmfData_Create();
238     data->unifiedData_ = std::move(unifiedData);
239     *status = ERR_OK;
240     return data;
241 }
242 
OH_Pasteboard_SetData(OH_Pasteboard * pasteboard,OH_UdmfData * data)243 int OH_Pasteboard_SetData(OH_Pasteboard* pasteboard, OH_UdmfData* data)
244 {
245     if (!IsPasteboardValid(pasteboard) || data == nullptr) {
246         return ERR_INVALID_PARAMETER;
247     }
248     int32_t ret = PasteboardClient::GetInstance()->SetUdsdData(*(data->unifiedData_));
249     if (ret != static_cast<int32_t>(PasteboardError::E_OK)) {
250         PASTEBOARD_HILOGE(
251             PASTEBOARD_MODULE_CAPI, "client OH_Pasteboard_SetData return invalid, result is %{public}d", ret);
252         return GetMappedCode(ret);
253     }
254     return ERR_OK;
255 }
256 
OH_Pasteboard_ClearData(OH_Pasteboard * pasteboard)257 int OH_Pasteboard_ClearData(OH_Pasteboard* pasteboard)
258 {
259     if (!IsPasteboardValid(pasteboard)) {
260         return ERR_INVALID_PARAMETER;
261     }
262     PasteboardClient::GetInstance()->Clear();
263     return ERR_OK;
264 }