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(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(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 taskExecutor_->PostTask([data]() { g_clipboard = data; }, TaskExecutor::TaskType::UI);
78 #endif
79 }
80
SetPixelMapData(const RefPtr<PixelMap> & pixmap,CopyOptions copyOption)81 void ClipboardImpl::SetPixelMapData(const RefPtr<PixelMap>& pixmap, CopyOptions copyOption)
82 {
83 CHECK_NULL_VOID(taskExecutor_);
84 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
85 auto shareOption = TransitionCopyOption(copyOption);
86 taskExecutor_->PostTask(
87 [pixmap, shareOption]() {
88 CHECK_NULL_VOID(pixmap);
89 auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
90 CHECK_NULL_VOID(pixmapOhos);
91 auto pasteData = OHOS::MiscServices::PasteboardClient::GetInstance()->CreatePixelMapData(
92 pixmapOhos->GetPixelMapSharedPtr());
93 CHECK_NULL_VOID(pasteData);
94 pasteData->SetShareOption(shareOption);
95 LOGI("Set pixmap to system clipboard");
96 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
97 },
98 TaskExecutor::TaskType::PLATFORM);
99 #else
100 taskExecutor_->PostTask([pixmap]() { g_pixmap = pixmap; }, TaskExecutor::TaskType::UI);
101 #endif
102 }
103
GetData(const std::function<void (const std::string &)> & callback,bool syncMode)104 void ClipboardImpl::GetData(const std::function<void(const std::string&)>& callback, bool syncMode)
105 {
106 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
107 if (!taskExecutor_ || !callback) {
108 return;
109 }
110
111 if (syncMode) {
112 GetDataSync(callback);
113 } else {
114 GetDataAsync(callback);
115 }
116 #else
117 if (syncMode) {
118 callback(g_clipboard);
119 return;
120 }
121 CHECK_NULL_VOID(taskExecutor_);
122 taskExecutor_->PostTask(
123 [callback, taskExecutor = WeakClaim(RawPtr(taskExecutor_)), textData = g_clipboard]() {
124 callback(textData);
125 },
126 TaskExecutor::TaskType::UI);
127 #endif
128 }
129
GetPixelMapData(const std::function<void (const RefPtr<PixelMap> &)> & callback,bool syncMode)130 void ClipboardImpl::GetPixelMapData(const std::function<void(const RefPtr<PixelMap>&)>& callback, bool syncMode)
131 {
132 if (!taskExecutor_ || !callback) {
133 return;
134 }
135 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
136 if (syncMode) {
137 GetPixelMapDataSync(callback);
138 } else {
139 GetPixelMapDataAsync(callback);
140 }
141 #else
142 if (syncMode) {
143 callback(g_pixmap);
144 } else {
145 taskExecutor_->PostTask([callback, taskExecutor = WeakClaim(RawPtr(taskExecutor_)),
146 imageData = g_pixmap]() { callback(imageData); },
147 TaskExecutor::TaskType::UI);
148 }
149 #endif
150 }
151
CreatePasteDataMix()152 RefPtr<PasteDataMix> ClipboardImpl::CreatePasteDataMix()
153 {
154 return AceType::MakeRefPtr<PasteDataImpl>();
155 }
156
AddPixelMapRecord(const RefPtr<PasteDataMix> & pasteData,const RefPtr<PixelMap> & pixmap)157 void ClipboardImpl::AddPixelMapRecord(const RefPtr<PasteDataMix>& pasteData, const RefPtr<PixelMap>& pixmap)
158 {
159 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
160 CHECK_NULL_VOID(taskExecutor_);
161 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
162 CHECK_NULL_VOID(peData);
163 auto pixmapOhos = AceType::DynamicCast<PixelMapOhos>(pixmap);
164 CHECK_NULL_VOID(pixmapOhos);
165 LOGI("add pixelMap record to pasteData");
166 peData->GetPasteDataData()->AddPixelMapRecord(pixmapOhos->GetPixelMapSharedPtr());
167 #endif
168 }
169
AddImageRecord(const RefPtr<PasteDataMix> & pasteData,const std::string & uri)170 void ClipboardImpl::AddImageRecord(const RefPtr<PasteDataMix>& pasteData, const std::string& uri)
171 {
172 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
173 CHECK_NULL_VOID(taskExecutor_);
174 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
175 CHECK_NULL_VOID(peData);
176 LOGI("add url record to pasteData, url: %{public}s", uri.c_str());
177 peData->GetPasteDataData()->AddUriRecord(OHOS::Uri(uri));
178 #endif
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 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
184 CHECK_NULL_VOID(taskExecutor_);
185 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
186 CHECK_NULL_VOID(peData);
187 LOGI("add text record to pasteData, text: %{public}s", selectedStr.c_str());
188 peData->GetPasteDataData()->AddTextRecord(selectedStr);
189 #endif
190 }
191
SetData(const RefPtr<PasteDataMix> & pasteData,CopyOptions copyOption)192 void ClipboardImpl::SetData(const RefPtr<PasteDataMix>& pasteData, CopyOptions copyOption)
193 {
194 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
195 auto shareOption = TransitionCopyOption(copyOption);
196 auto peData = AceType::DynamicCast<PasteDataImpl>(pasteData);
197 CHECK_NULL_VOID(peData);
198 taskExecutor_->PostTask(
199 [peData, shareOption]() {
200 auto pasteData = peData->GetPasteDataData();
201 pasteData->SetShareOption(shareOption);
202 LOGI("add pasteData to clipboard, shareOption: %{public}d", shareOption);
203 OHOS::MiscServices::PasteboardClient::GetInstance()->SetPasteData(*pasteData);
204 },
205 TaskExecutor::TaskType::PLATFORM);
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 #endif
224 }
225
226 #ifdef SYSTEM_CLIPBOARD_SUPPORTED
GetPasteDataData()227 std::shared_ptr<MiscServices::PasteData> PasteDataImpl::GetPasteDataData()
228 {
229 if (pasteData_ == nullptr) {
230 pasteData_ = std::make_shared<MiscServices::PasteData>();
231 }
232 return pasteData_;
233 }
SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)234 void PasteDataImpl::SetUnifiedData(std::shared_ptr<MiscServices::PasteData> pasteData)
235 {
236 pasteData_ = pasteData;
237 }
238
GetDataSync(const std::function<void (const std::string &)> & callback)239 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&)>& callback)
240 {
241 std::string result;
242 taskExecutor_->PostSyncTask(
243 [&result]() {
244 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
245 CHECK_NULL_VOID(has);
246 OHOS::MiscServices::PasteData pasteData;
247 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
248 CHECK_NULL_VOID(ok);
249 auto textData = pasteData.GetPrimaryText();
250 CHECK_NULL_VOID(textData);
251 result = *textData;
252 },
253 TaskExecutor::TaskType::PLATFORM);
254 callback(result);
255 }
256
GetDataAsync(const std::function<void (const std::string &)> & callback)257 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&)>& callback)
258 {
259 taskExecutor_->PostTask(
260 [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
261 auto taskExecutor = weakExecutor.Upgrade();
262 CHECK_NULL_VOID(taskExecutor);
263 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
264 if (!has) {
265 LOGW("GetDataAsync: SystemKeyboardData is not exist from MiscServices");
266 taskExecutor->PostTask([callback]() { callback(""); }, TaskExecutor::TaskType::UI);
267 return;
268 }
269 OHOS::MiscServices::PasteData pasteData;
270 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
271 if (!ok) {
272 LOGW("GetDataAsync: Get SystemKeyboardData fail from MiscServices");
273 taskExecutor->PostTask([callback]() { callback(""); }, TaskExecutor::TaskType::UI);
274 return;
275 }
276 std::string resText;
277 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
278 if (pasteDataRecord == nullptr) {
279 continue;
280 }
281 if (pasteDataRecord->GetPlainText() != nullptr) {
282 auto textData = pasteDataRecord->GetPlainText();
283 resText.append(*textData);
284 }
285 }
286 if (resText.empty()) {
287 LOGW("GetDataAsync: Get SystemKeyboardTextData fail from MiscServices");
288 taskExecutor->PostTask([callback]() { callback(""); }, TaskExecutor::TaskType::UI);
289 return;
290 }
291 auto result = resText;
292 taskExecutor->PostTask([callback, result]() { callback(result); }, TaskExecutor::TaskType::UI);
293 },
294 TaskExecutor::TaskType::PLATFORM);
295 }
296
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)297 void ClipboardImpl::GetDataSync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
298 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
299 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
300 {
301 LOGI("get data from clipboard, sync");
302 OHOS::MiscServices::PasteData pasteData;
303 taskExecutor_->PostSyncTask(
304 [&pasteData]() {
305 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
306 CHECK_NULL_VOID(has);
307 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
308 CHECK_NULL_VOID(ok);
309 },
310 TaskExecutor::TaskType::PLATFORM);
311
312 auto count = pasteData.GetRecordCount();
313 size_t index = 0;
314 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
315 index++;
316 if (pasteDataRecord == nullptr) {
317 continue;
318 }
319 bool isLastRecord = index == count;
320 if (pasteDataRecord->GetPlainText() != nullptr) {
321 auto textData = pasteDataRecord->GetPlainText();
322 auto result = *textData;
323 textCallback(result, isLastRecord);
324 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
325 auto imageData = pasteDataRecord->GetPixelMap();
326 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
327 pixelMapCallback(result, isLastRecord);
328 } else if (pasteDataRecord->GetUri() != nullptr) {
329 auto textData = pasteDataRecord->GetUri();
330 auto result = (*textData).ToString();
331 urlCallback(result, isLastRecord);
332 }
333 }
334 }
335
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)336 void ClipboardImpl::GetDataAsync(const std::function<void(const std::string&, bool isLastRecord)>& textCallback,
337 const std::function<void(const RefPtr<PixelMap>&, bool isLastRecord)>& pixelMapCallback,
338 const std::function<void(const std::string&, bool isLastRecord)>& urlCallback)
339 {
340 LOGI("get data from clipboard, async");
341 taskExecutor_->PostTask(
342 [textCallback, pixelMapCallback, urlCallback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
343 auto taskExecutor = weakExecutor.Upgrade();
344 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
345 CHECK_NULL_VOID(has);
346 OHOS::MiscServices::PasteData pasteData;
347 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
348 CHECK_NULL_VOID(ok);
349 auto count = pasteData.GetRecordCount();
350 size_t index = 0;
351 for (const auto& pasteDataRecord : pasteData.AllRecords()) {
352 index++;
353 if (pasteDataRecord == nullptr) {
354 continue;
355 }
356 bool isLastRecord = index == count;
357 if (pasteDataRecord->GetPlainText() != nullptr) {
358 auto textData = pasteDataRecord->GetPlainText();
359 auto result = *textData;
360 taskExecutor->PostTask(
361 [textCallback, result, isLastRecord]() { textCallback(result, isLastRecord); },
362 TaskExecutor::TaskType::UI);
363 } else if (pasteDataRecord->GetPixelMap() != nullptr) {
364 auto imageData = pasteDataRecord->GetPixelMap();
365 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
366 taskExecutor->PostTask(
367 [pixelMapCallback, result, isLastRecord]() { pixelMapCallback(result, isLastRecord); },
368 TaskExecutor::TaskType::UI);
369 } else if (pasteDataRecord->GetUri() != nullptr) {
370 auto textData = pasteDataRecord->GetUri();
371 auto result = (*textData).ToString();
372 taskExecutor->PostTask([urlCallback, result, isLastRecord]() { urlCallback(result, isLastRecord); },
373 TaskExecutor::TaskType::UI);
374 }
375 }
376 },
377 TaskExecutor::TaskType::PLATFORM);
378 }
379
GetPixelMapDataSync(const std::function<void (const RefPtr<PixelMap> &)> & callback)380 void ClipboardImpl::GetPixelMapDataSync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
381 {
382 RefPtr<PixelMap> pixmap;
383 taskExecutor_->PostSyncTask(
384 [&pixmap]() {
385 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
386 CHECK_NULL_VOID(has);
387 OHOS::MiscServices::PasteData pasteData;
388 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
389 CHECK_NULL_VOID(ok);
390 auto imageData = pasteData.GetPrimaryPixelMap();
391 CHECK_NULL_VOID(imageData);
392 pixmap = AceType::MakeRefPtr<PixelMapOhos>(imageData);
393 },
394 TaskExecutor::TaskType::PLATFORM);
395 callback(pixmap);
396 }
397
GetPixelMapDataAsync(const std::function<void (const RefPtr<PixelMap> &)> & callback)398 void ClipboardImpl::GetPixelMapDataAsync(const std::function<void(const RefPtr<PixelMap>&)>& callback)
399 {
400 taskExecutor_->PostTask(
401 [callback, weakExecutor = WeakClaim(RawPtr(taskExecutor_))]() {
402 auto taskExecutor = weakExecutor.Upgrade();
403 CHECK_NULL_VOID(taskExecutor);
404 auto has = OHOS::MiscServices::PasteboardClient::GetInstance()->HasPasteData();
405 if (!has) {
406 LOGW("SystemKeyboardData is not exist from MiscServices");
407 taskExecutor->PostTask([callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI);
408 return;
409 }
410 OHOS::MiscServices::PasteData pasteData;
411 auto ok = OHOS::MiscServices::PasteboardClient::GetInstance()->GetPasteData(pasteData);
412 if (!ok) {
413 LOGW("Get SystemKeyboardData fail from MiscServices");
414 taskExecutor->PostTask([callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI);
415 return;
416 }
417 auto imageData = pasteData.GetPrimaryPixelMap();
418 if (!imageData) {
419 LOGW("Get SystemKeyboardImageData fail from MiscServices");
420 taskExecutor->PostTask([callback]() { callback(nullptr); }, TaskExecutor::TaskType::UI);
421 return;
422 }
423 auto result = AceType::MakeRefPtr<PixelMapOhos>(imageData);
424 taskExecutor->PostTask([callback, result]() { callback(result); }, TaskExecutor::TaskType::UI);
425 },
426 TaskExecutor::TaskType::PLATFORM);
427 }
428 #endif
429
Clear()430 void ClipboardImpl::Clear() {}
431
432 } // namespace OHOS::Ace
433