1 /*
2 * Copyright (c) 2022 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 "adapter/ohos/capability/clipboard/clipboard_impl.h"
17
18 #include "adapter/ohos/osal/pixel_map_ohos.h"
19 #include "base/utils/utils.h"
20
21 namespace OHOS::Ace {
22 #ifndef SYSTEM_CLIPBOARD_SUPPORTED
23 namespace {
24 std::string g_clipboard;
25 RefPtr<PixelMap> g_pixmap;
26 } // namespace
27 #endif
28
29 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
TransitionCopyOption(CopyOptions copyOption)30 MiscServices::ShareOption TransitionCopyOption(CopyOptions copyOption)
31 {
32 auto shareOption = MiscServices::ShareOption::InApp;
33 switch (copyOption) {
34 case CopyOptions::InApp:
35 shareOption = MiscServices::ShareOption::InApp;
36 break;
37 case CopyOptions::Local:
38 shareOption = MiscServices::ShareOption::LocalDevice;
39 break;
40 case CopyOptions::Distributed:
41 shareOption = MiscServices::ShareOption::CrossDevice;
42 break;
43 default:
44 break;
45 }
46 return shareOption;
47 }
48 #endif
49
HasData(const std::function<void (bool hasData)> & callback)50 void ClipboardImpl::HasData(const std::function<void(bool hasData)>& callback)
51 {
52 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
53 bool hasData = false;
54 CHECK_NULL_VOID_NOLOG(taskExecutor_);
55 taskExecutor_->PostSyncTask(
56 [&hasData]() { hasData = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData(); },
57 TaskExecutor::TaskType::PLATFORM);
58 callback(hasData);
59 #endif
60 }
61
SetData(const std::string & data,CopyOptions copyOption,bool isDragData)62 void ClipboardImpl::SetData(const std::string& data, CopyOptions copyOption, bool isDragData)
63 {
64 CHECK_NULL_VOID_NOLOG(taskExecutor_);
65 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
66 auto shareOption = TransitionCopyOption(copyOption);
67 taskExecutor_->PostTask(
68 [data, shareOption, isDragData]() {
69 auto pasteData = OHOS::MiscServices::PasteboardClient::GetInstance()->CreatePlainTextData(data);
70 CHECK_NULL_VOID(pasteData);
71 pasteData->SetShareOption(shareOption);
72 pasteData->SetDraggedDataFlag(isDragData);
73 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
74 },
75 TaskExecutor::TaskType::PLATFORM);
76 #else
77 LOGI("Current device doesn't support system clipboard");
78 taskExecutor_->PostTask([data]() { g_clipboard = data; }, TaskExecutor::TaskType::UI);
79 #endif
80 }
81
SetPixelMapData(const RefPtr<PixelMap> & pixmap,CopyOptions copyOption)82 void ClipboardImpl::SetPixelMapData(const RefPtr<PixelMap>& pixmap, CopyOptions copyOption)
83 {
84 CHECK_NULL_VOID_NOLOG(taskExecutor_);
85 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
86 auto shareOption = TransitionCopyOption(copyOption);
87 taskExecutor_->PostTask(
88 [pixmap, shareOption]() {
89 CHECK_NULL_VOID(pixmap);
90 auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
91 CHECK_NULL_VOID_NOLOG(pixmapOhos);
92 auto pasteData = OHOS::MiscServices::PasteboardClient::GetInstance()->CreatePixelMapData(
93 pixmapOhos->GetPixelMapSharedPtr());
94 CHECK_NULL_VOID(pasteData);
95 pasteData->SetShareOption(shareOption);
96 LOGI("Set pixmap to system clipboard");
97 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
98 },
99 TaskExecutor::TaskType::PLATFORM);
100 #else
101 LOGI("Current device doesn't support system clipboard");
102 taskExecutor_->PostTask([pixmap]() { g_pixmap = pixmap; }, TaskExecutor::TaskType::UI);
103 #endif
104 }
105
GetData(const std::function<void (const std::string &)> & callback,bool syncMode)106 void ClipboardImpl::GetData(const std::function<void(const std::string&)>& callback, bool syncMode)
107 {
108 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
109 if (!taskExecutor_ || !callback) {
110 return;
111 }
112
113 if (syncMode) {
114 GetDataSync(callback);
115 } else {
116 GetDataAsync(callback);
117 }
118 #else
119 LOGI("Current device doesn't support system clipboard");
120 if (syncMode) {
121 callback(g_clipboard);
122 return;
123 }
124 CHECK_NULL_VOID_NOLOG(taskExecutor_);
125 taskExecutor_->PostTask(
126 [callback, taskExecutor = WeakClaim(RawPtr(taskExecutor_)), textData = g_clipboard]() {
127 callback(textData);
128 },
129 TaskExecutor::TaskType::UI);
130 #endif
131 }
132
GetPixelMapData(const std::function<void (const RefPtr<PixelMap> &)> & callback,bool syncMode)133 void ClipboardImpl::GetPixelMapData(const std::function<void(const RefPtr<PixelMap>&)>& callback, bool syncMode)
134 {
135 if (!taskExecutor_ || !callback) {
136 return;
137 }
138 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
139 if (syncMode) {
140 GetPixelMapDataSync(callback);
141 } else {
142 GetPixelMapDataAsync(callback);
143 }
144 #else
145 LOGI("Current device doesn't support system clipboard");
146 if (syncMode) {
147 callback(g_pixmap);
148 } else {
149 taskExecutor_->PostTask([callback, taskExecutor = WeakClaim(RawPtr(taskExecutor_)),
150 imageData = g_pixmap]() { callback(imageData); },
151 TaskExecutor::TaskType::UI);
152 }
153 #endif
154 }
155
CreatePasteDataMix()156 RefPtr<PasteDataMix> ClipboardImpl::CreatePasteDataMix()
157 {
158 return AceType::MakeRefPtr<PasteDataImpl>();
159 }
160
AddPixelMapRecord(const RefPtr<PasteDataMix> & pasteData,const RefPtr<PixelMap> & pixmap)161 void ClipboardImpl::AddPixelMapRecord(const RefPtr<PasteDataMix>& pasteData, const RefPtr<PixelMap>& pixmap)
162 {
163 CHECK_NULL_VOID_NOLOG(taskExecutor_);
164 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
165 CHECK_NULL_VOID(peData);
166 auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
167 CHECK_NULL_VOID_NOLOG(pixmapOhos);
168 LOGI("add pixelMap record to pasteData");
169 peData->GetPasteDataData()->AddPixelMapRecord(pixmapOhos->GetPixelMapSharedPtr());
170 }
171
AddImageRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & uri)172 void ClipboardImpl::AddImageRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& uri)
173 {
174 CHECK_NULL_VOID_NOLOG(taskExecutor_);
175 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
176 CHECK_NULL_VOID(peData);
177 LOGI("add url record to pasteData, url: %{public}s", uri.c_str());
178 peData->GetPasteDataData()->AddUriRecord(OHOS::Uri(uri));
179 }
180
AddTextRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & selectedStr)181 void ClipboardImpl::AddTextRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& selectedStr)
182 {
183 CHECK_NULL_VOID_NOLOG(taskExecutor_);
184 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
185 CHECK_NULL_VOID(peData);
186 LOGI("add text record to pasteData, text: %{public}s", selectedStr.c_str());
187 peData->GetPasteDataData()->AddTextRecord(selectedStr);
188 }
189
SetData(const RefPtr<PasteDataMix> & pasteData,CopyOptions copyOption)190 void ClipboardImpl::SetData(const RefPtr<PasteDataMix>& pasteData, CopyOptions copyOption)
191 {
192 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
193 auto shareOption = TransitionCopyOption(copyOption);
194 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
195 CHECK_NULL_VOID(peData);
196 taskExecutor_->PostTask(
197 [peData, shareOption]() {
198 auto pasteData = peData->GetPasteDataData();
199 pasteData->SetShareOption(shareOption);
200 LOGI("add pasteData to clipboard, shareOption: %{public}d", shareOption);
201 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
202 },
203 TaskExecutor::TaskType::PLATFORM);
204 #else
205 LOGI("Current device doesn't support system clipboard");
206 #endif
207 }
208
GetData(const std::function<void (const std::string &,bool isLastRecord)> & textCallback,const std::function<void (const RefPtr<PixelMap> &,bool isLastRecord)> & pixelMapCallback,const std::function<void (const std::string &,bool isLastRecord)> & urlCallback,bool syncMode)209 void ClipboardImpl::GetData(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
210 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
211 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback, bool syncMode)
212 {
213 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
214 if (!taskExecutor_ || !textCallback || !pixelMapCallback || !urlCallback) {
215 return;
216 }
217
218 if (syncMode) {
219 GetDataSync(textCallback, pixelMapCallback, urlCallback);
220 } else {
221 GetDataAsync(textCallback, pixelMapCallback, urlCallback);
222 }
223 #else
224 LOGI("Current device doesn't support system clipboard");
225 #endif
226 }
227
228 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
GetPasteDataData()229 std::shared_ptr<MiscServices::PasteData> PasteDataImpl::GetPasteDataData()
230 {
231 if (pasteData_ == nullptr) {
232 pasteData_ = std::make_shared<MiscServices::PasteData>();
233 }
234 return pasteData_;
235 }
SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)236 void PasteDataImpl::SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)
237 {
238 pasteData_ = pasteData;
239 }
240
GetDataSync(const std::function<void (const std::string &)> & callback)241 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&)>& callback)
242 {
243 std::string result;
244 taskExecutor_->PostSyncTask(
245 [&result]() {
246 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
247 CHECK_NULL_VOID(has);
248 OHOS::MiscServices::PasteData pasteData;
249 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
250 CHECK_NULL_VOID(ok);
251 auto textData = pasteData.GetPrimaryText();
252 CHECK_NULL_VOID(textData);
253 result = *textData;
254 },
255 TaskExecutor::TaskType::PLATFORM);
256 callback(result);
257 }
258
GetDataAsync(const std::function<void (const std::string &)> & callback)259 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&)>& callback)
260 {
261 taskExecutor_->PostTask(
262 [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
263 auto taskExecutor = weakExecutor.Upgrade();
264 CHECK_NULL_VOID(taskExecutor);
265 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
266 if (!has) {
267 LOGE("GetDataAsync: SystemKeyboardData is not exist from MiscServices");
268 taskExecutor->PostTask([callback]() { callback(""); }, TaskExecutor::TaskType::UI);
269 return;
270 }
271 OHOS::MiscServices::PasteData pasteData;
272 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
273 if (!ok) {
274 LOGE("GetDataAsync: Get SystemKeyboardData fail from MiscServices");
275 taskExecutor->PostTask([callback]() { callback(""); }, TaskExecutor::TaskType::UI);
276 return;
277 }
278 auto textData = pasteData.GetPrimaryText();
279 if (!textData) {
280 LOGE("GetDataAsync: Get SystemKeyboardTextData fail from MiscServices");
281 taskExecutor->PostTask([callback]() { callback(""); }, TaskExecutor::TaskType::UI);
282 return;
283 }
284 auto result = *textData;
285 taskExecutor->PostTask([callback, result]() { callback(result); }, TaskExecutor::TaskType::UI);
286 },
287 TaskExecutor::TaskType::PLATFORM);
288 }
289
GetDataSync(const std::function<void (const std::string &,bool isLastRecord)> & textCallback,const std::function<void (const RefPtr<PixelMap> &,bool isLastRecord)> & pixelMapCallback,const std::function<void (const std::string &,bool isLastRecord)> & urlCallback)290 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
291 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
292 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
293 {
294 LOGI("get data from clipboard, sync");
295 OHOS::MiscServices::PasteData pasteData;
296 taskExecutor_->PostSyncTask(
297 [&pasteData]() {
298 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
299 CHECK_NULL_VOID(has);
300 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
301 CHECK_NULL_VOID(ok);
302 },
303 TaskExecutor::TaskType::PLATFORM);
304
305 auto count = pasteData.GetRecordCount();
306 size_t index = 0;
307 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
308 index++;
309 if (pasteDataRecord == nullptr) {
310 continue;
311 }
312 bool isLastRecord = index == count;
313 if (pasteDataRecord->GetPlainText() != nullptr) {
314 auto textData = pasteDataRecord->GetPlainText();
315 auto result = *textData;
316 textCallback(result, isLastRecord);
317 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
318 auto imageData = pasteDataRecord->GetPixelMap();
319 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
320 pixelMapCallback(result, isLastRecord);
321 } else if (pasteDataRecord->GetUri() != nullptr) {
322 auto textData = pasteDataRecord->GetUri();
323 auto result = (*textData).ToString();
324 urlCallback(result, isLastRecord);
325 }
326 }
327 }
328
GetDataAsync(const std::function<void (const std::string &,bool isLastRecord)> & textCallback,const std::function<void (const RefPtr<PixelMap> &,bool isLastRecord)> & pixelMapCallback,const std::function<void (const std::string &,bool isLastRecord)> & urlCallback)329 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
330 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
331 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
332 {
333 LOGI("get data from clipboard, async");
334 taskExecutor_->PostTask(
335 [textCallback, pixelMapCallback, urlCallback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
336 auto taskExecutor = weakExecutor.Upgrade();
337 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
338 CHECK_NULL_VOID(has);
339 OHOS::MiscServices::PasteData pasteData;
340 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
341 CHECK_NULL_VOID(ok);
342 auto count = pasteData.GetRecordCount();
343 size_t index = 0;
344 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
345 index++;
346 if (pasteDataRecord == nullptr) {
347 continue;
348 }
349 bool isLastRecord = index == count;
350 if (pasteDataRecord->GetPlainText() != nullptr) {
351 auto textData = pasteDataRecord->GetPlainText();
352 auto result = *textData;
353 taskExecutor->PostTask(
354 [textCallback, result, isLastRecord]() { textCallback(result, isLastRecord); },
355 TaskExecutor::TaskType::UI);
356 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
357 auto imageData = pasteDataRecord->GetPixelMap();
358 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
359 taskExecutor->PostTask(
360 [pixelMapCallback, result, isLastRecord]() { pixelMapCallback(result, isLastRecord); },
361 TaskExecutor::TaskType::UI);
362 } else if (pasteDataRecord->GetUri() != nullptr) {
363 auto textData = pasteDataRecord->GetUri();
364 auto result = (*textData).ToString();
365 taskExecutor->PostTask([urlCallback, result, isLastRecord]() { urlCallback(result, isLastRecord); },
366 TaskExecutor::TaskType::UI);
367 }
368 }
369 },
370 TaskExecutor::TaskType::PLATFORM);
371 }
372
GetPixelMapDataSync(const std::function<void (const RefPtr<PixelMap> &)> & callback)373 void ClipboardImpl::GetPixelMapDataSync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
374 {
375 RefPtr<PixelMap> pixmap;
376 taskExecutor_->PostSyncTask(
377 [&pixmap]() {
378 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
379 CHECK_NULL_VOID(has);
380 OHOS::MiscServices::PasteData pasteData;
381 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
382 CHECK_NULL_VOID(ok);
383 auto imageData = pasteData.GetPrimaryPixelMap();
384 CHECK_NULL_VOID(imageData);
385 pixmap = AceType::MakeRefPtr<PixelMapOhos>(imageData);
386 },
387 TaskExecutor::TaskType::PLATFORM);
388 callback(pixmap);
389 }
390
GetPixelMapDataAsync(const std::function<void (const RefPtr<PixelMap> &)> & callback)391 void ClipboardImpl::GetPixelMapDataAsync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
392 {
393 taskExecutor_->PostTask(
394 [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
395 auto taskExecutor = weakExecutor.Upgrade();
396 CHECK_NULL_VOID(taskExecutor);
397 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
398 if (!has) {
399 LOGE("SystemKeyboardData is not exist from MiscServices");
400 taskExecutor->PostTask([callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI);
401 return;
402 }
403 OHOS::MiscServices::PasteData pasteData;
404 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
405 if (!ok) {
406 LOGE("Get SystemKeyboardData fail from MiscServices");
407 taskExecutor->PostTask([callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI);
408 return;
409 }
410 auto imageData = pasteData.GetPrimaryPixelMap();
411 if (!imageData) {
412 LOGE("Get SystemKeyboardImageData fail from MiscServices");
413 taskExecutor->PostTask([callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI);
414 return;
415 }
416 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
417 taskExecutor->PostTask([callback, result]() { callback(result); }, TaskExecutor::TaskType::UI);
418 },
419 TaskExecutor::TaskType::PLATFORM);
420 }
421 #endif
422
Clear()423 void ClipboardImpl::Clear() {}
424
425 } // namespace OHOS::Ace
426