1 /*
2 * Copyright (c) 2021-2023 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 <if_system_ability_manager.h>
17 #include <ipc_skeleton.h>
18 #include <iservice_registry.h>
19 #include <chrono>
20
21 #include "hiview_adapter.h"
22 #include "hitrace_meter.h"
23 #include "pasteboard_client.h"
24 #include "pasteboard_error.h"
25 #include "pasteboard_load_callback.h"
26 #include "pasteboard_observer.h"
27 #include "string_ex.h"
28 #include "system_ability_definition.h"
29 #include "pasteboard_web_controller.h"
30
31 using namespace OHOS::Media;
32
33 namespace OHOS {
34 namespace MiscServices {
35 constexpr const int32_t HITRACE_GETPASTEDATA = 0;
36 constexpr int32_t LOADSA_TIMEOUT_MS = 10000;
37 sptr<IPasteboardService> PasteboardClient::pasteboardServiceProxy_;
38 PasteboardClient::StaticDestoryMonitor PasteboardClient::staticDestoryMonitor_;
39 std::mutex PasteboardClient::instanceLock_;
40 std::condition_variable PasteboardClient::proxyConVar_;
PasteboardClient()41 PasteboardClient::PasteboardClient(){};
~PasteboardClient()42 PasteboardClient::~PasteboardClient()
43 {
44 if (pasteboardServiceProxy_ != nullptr && !staticDestoryMonitor_.IsDestoryed()) {
45 auto remoteObject = pasteboardServiceProxy_->AsObject();
46 if (remoteObject != nullptr) {
47 remoteObject->RemoveDeathRecipient(deathRecipient_);
48 }
49 }
50 }
51
CreateHtmlTextRecord(const std::string & htmlText)52 std::shared_ptr<PasteDataRecord> PasteboardClient::CreateHtmlTextRecord(const std::string &htmlText)
53 {
54 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New text record");
55 return PasteDataRecord::NewHtmlRecord(htmlText);
56 }
57
CreateWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)58 std::shared_ptr<PasteDataRecord> PasteboardClient::CreateWantRecord(std::shared_ptr<OHOS::AAFwk::Want> want)
59 {
60 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New want record");
61 return PasteDataRecord::NewWantRecord(std::move(want));
62 }
63
CreatePlainTextRecord(const std::string & text)64 std::shared_ptr<PasteDataRecord> PasteboardClient::CreatePlainTextRecord(const std::string &text)
65 {
66 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New text record");
67 return PasteDataRecord::NewPlaintTextRecord(text);
68 }
69
CreatePixelMapRecord(std::shared_ptr<PixelMap> pixelMap)70 std::shared_ptr<PasteDataRecord> PasteboardClient::CreatePixelMapRecord(std::shared_ptr<PixelMap> pixelMap)
71 {
72 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New pixelMap record");
73 return PasteDataRecord::NewPixelMapRecord(std::move(pixelMap));
74 }
75
CreateUriRecord(const OHOS::Uri & uri)76 std::shared_ptr<PasteDataRecord> PasteboardClient::CreateUriRecord(const OHOS::Uri &uri)
77 {
78 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New uri record");
79 return PasteDataRecord::NewUriRecord(uri);
80 }
81
CreateKvRecord(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)82 std::shared_ptr<PasteDataRecord> PasteboardClient::CreateKvRecord(
83 const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
84 {
85 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New kv record");
86 return PasteDataRecord::NewKvRecord(mimeType, arrayBuffer);
87 }
88
CreateHtmlData(const std::string & htmlText)89 std::shared_ptr<PasteData> PasteboardClient::CreateHtmlData(const std::string &htmlText)
90 {
91 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New htmlText data");
92 auto pasteData = std::make_shared<PasteData>();
93 pasteData->AddHtmlRecord(htmlText);
94 return pasteData;
95 }
96
CreateWantData(std::shared_ptr<OHOS::AAFwk::Want> want)97 std::shared_ptr<PasteData> PasteboardClient::CreateWantData(std::shared_ptr<OHOS::AAFwk::Want> want)
98 {
99 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New want data");
100 auto pasteData = std::make_shared<PasteData>();
101 pasteData->AddWantRecord(std::move(want));
102 return pasteData;
103 }
104
CreatePlainTextData(const std::string & text)105 std::shared_ptr<PasteData> PasteboardClient::CreatePlainTextData(const std::string &text)
106 {
107 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New plain data");
108 auto pasteData = std::make_shared<PasteData>();
109 pasteData->AddTextRecord(text);
110 return pasteData;
111 }
112
CreatePixelMapData(std::shared_ptr<PixelMap> pixelMap)113 std::shared_ptr<PasteData> PasteboardClient::CreatePixelMapData(std::shared_ptr<PixelMap> pixelMap)
114 {
115 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New pixelMap data");
116 auto pasteData = std::make_shared<PasteData>();
117 pasteData->AddPixelMapRecord(std::move(pixelMap));
118 return pasteData;
119 }
120
CreateUriData(const OHOS::Uri & uri)121 std::shared_ptr<PasteData> PasteboardClient::CreateUriData(const OHOS::Uri &uri)
122 {
123 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New uri data");
124 auto pasteData = std::make_shared<PasteData>();
125 pasteData->AddUriRecord(uri);
126 return pasteData;
127 }
128
CreateKvData(const std::string & mimeType,const std::vector<uint8_t> & arrayBuffer)129 std::shared_ptr<PasteData> PasteboardClient::CreateKvData(
130 const std::string &mimeType, const std::vector<uint8_t> &arrayBuffer)
131 {
132 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "New Kv data");
133 auto pasteData = std::make_shared<PasteData>();
134 pasteData->AddKvRecord(mimeType, arrayBuffer);
135 return pasteData;
136 }
137
Clear()138 void PasteboardClient::Clear()
139 {
140 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Clear start.");
141 if (!IsServiceAvailable()) {
142 return;
143 }
144 pasteboardServiceProxy_->Clear();
145 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "Clear end.");
146 return;
147 }
148
GetPasteData(PasteData & pasteData)149 int32_t PasteboardClient::GetPasteData(PasteData &pasteData)
150 {
151 StartAsyncTrace(HITRACE_TAG_MISC, "PasteboardClient::GetPasteData", HITRACE_GETPASTEDATA);
152 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "GetPasteData start.");
153 if (!IsServiceAvailable()) {
154 return static_cast<int32_t>(PasteboardError::E_SA_DIED);
155 }
156 int32_t ret = pasteboardServiceProxy_->GetPasteData(pasteData);
157 RebuildWebviewPasteData(pasteData);
158 RetainUri(pasteData);
159 FinishAsyncTrace(HITRACE_TAG_MISC, "PasteboardClient::GetPasteData", HITRACE_GETPASTEDATA);
160 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "GetPasteData end.");
161 return ret;
162 }
163
RebuildWebviewPasteData(PasteData & pasteData)164 void PasteboardClient::RebuildWebviewPasteData(PasteData &pasteData)
165 {
166 if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG || pasteData.GetPrimaryHtml() == nullptr) {
167 return;
168 }
169 auto PasteboardWebController = PasteboardWebController::GetInstance();
170 PasteboardWebController.RebuildHtml(std::make_shared<PasteData>(pasteData));
171 }
172
RetainUri(PasteData & pasteData)173 void PasteboardClient::RetainUri(PasteData &pasteData)
174 {
175 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start");
176 if (!pasteData.IsLocalPaste()) {
177 return;
178 }
179 // clear convert uri
180 for (size_t i = 0; i < pasteData.GetRecordCount(); ++i) {
181 auto record = pasteData.GetRecordAt(0);
182 if (record != nullptr) {
183 record->SetConvertUri("");
184 }
185 }
186 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end");
187 }
188
HasPasteData()189 bool PasteboardClient::HasPasteData()
190 {
191 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "HasPasteData start.");
192 if (!IsServiceAvailable()) {
193 return false;
194 }
195 return pasteboardServiceProxy_->HasPasteData();
196 }
197
SetPasteData(PasteData & pasteData)198 int32_t PasteboardClient::SetPasteData(PasteData &pasteData)
199 {
200 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "SetPasteData start.");
201 if (!IsServiceAvailable()) {
202 return static_cast<int32_t>(PasteboardError::E_SA_DIED);
203 }
204 std::shared_ptr<std::string> html = pasteData.GetPrimaryHtml();
205 if (pasteData.GetTag() != PasteData::WEBVIEW_PASTEDATA_TAG || html == nullptr) {
206 return pasteboardServiceProxy_->SetPasteData(pasteData);
207 }
208 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "SetPasteData from webview start.");
209 std::shared_ptr<std::string> primaryText = pasteData.GetRecordAt(0)->GetPlainText();
210 auto PasteboardWebController = PasteboardWebController::GetInstance();
211 std::shared_ptr<PasteData> webPasteData = PasteboardWebController.SplitHtml(html);
212 webPasteData->RemoveRecordAt(webPasteData->GetRecordCount() - 1);
213 std::string mimeType = MIMETYPE_TEXT_PLAIN;
214 PasteDataRecord::Builder builder(MIMETYPE_TEXT_HTML);
215 std::shared_ptr<PasteDataRecord> pasteDataRecord =
216 builder.SetMimeType(mimeType).SetPlainText(primaryText).SetHtmlText(html).Build();
217 webPasteData->AddRecord(pasteDataRecord);
218 webPasteData->SetTag(PasteData::WEBVIEW_PASTEDATA_TAG);
219 return pasteboardServiceProxy_->SetPasteData(*webPasteData);
220 }
221
AddPasteboardChangedObserver(sptr<PasteboardObserver> callback)222 void PasteboardClient::AddPasteboardChangedObserver(sptr<PasteboardObserver> callback)
223 {
224 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start.");
225 if (callback == nullptr) {
226 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "input nullptr.");
227 return;
228 }
229 if (!IsServiceAvailable()) {
230 return;
231 }
232 pasteboardServiceProxy_->AddPasteboardChangedObserver(callback);
233 return;
234 }
235
AddPasteboardEventObserver(sptr<PasteboardObserver> callback)236 void PasteboardClient::AddPasteboardEventObserver(sptr<PasteboardObserver> callback)
237 {
238 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start.");
239 if (callback == nullptr) {
240 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "input nullptr.");
241 return;
242 }
243 if (!IsServiceAvailable()) {
244 return;
245 }
246 pasteboardServiceProxy_->AddPasteboardEventObserver(callback);
247 }
248
RemovePasteboardChangedObserver(sptr<PasteboardObserver> callback)249 void PasteboardClient::RemovePasteboardChangedObserver(sptr<PasteboardObserver> callback)
250 {
251 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start.");
252 if (!IsServiceAvailable()) {
253 return;
254 }
255 if (callback == nullptr) {
256 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "remove all.");
257 pasteboardServiceProxy_->RemoveAllChangedObserver();
258 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end.");
259 return;
260 }
261 pasteboardServiceProxy_->RemovePasteboardChangedObserver(callback);
262 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end.");
263 return;
264 }
265
RemovePasteboardEventObserver(sptr<PasteboardObserver> callback)266 void PasteboardClient::RemovePasteboardEventObserver(sptr<PasteboardObserver> callback)
267 {
268 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "start.");
269 if (!IsServiceAvailable()) {
270 return;
271 }
272 if (callback == nullptr) {
273 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "remove all.");
274 pasteboardServiceProxy_->RemoveAllEventObserver();
275 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end.");
276 return;
277 }
278 pasteboardServiceProxy_->RemovePasteboardEventObserver(callback);
279 PASTEBOARD_HILOGD(PASTEBOARD_MODULE_CLIENT, "end.");
280 }
281
IsServiceAvailable()282 inline bool PasteboardClient::IsServiceAvailable()
283 {
284 if (pasteboardServiceProxy_ == nullptr) {
285 PASTEBOARD_HILOGW(PASTEBOARD_MODULE_CLIENT, "Redo ConnectService");
286 ConnectService();
287 }
288
289 if (pasteboardServiceProxy_ == nullptr) {
290 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Service proxy null.");
291 return false;
292 }
293 return true;
294 }
295
ConnectService()296 void PasteboardClient::ConnectService()
297 {
298 std::unique_lock<std::mutex> lock(instanceLock_);
299 if (pasteboardServiceProxy_ != nullptr) {
300 return;
301 }
302 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "ConnectService start.");
303 sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
304 if (samgrProxy == nullptr) {
305 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Get SystemAbilityManager failed.");
306 pasteboardServiceProxy_ = nullptr;
307 return;
308 }
309 sptr<IRemoteObject> remoteObject = samgrProxy->CheckSystemAbility(PASTEBOARD_SERVICE_ID);
310 if (remoteObject != nullptr) {
311 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Get PasteboardServiceProxy succeed.");
312 if (deathRecipient_ == nullptr) {
313 deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new PasteboardSaDeathRecipient());
314 }
315 remoteObject->AddDeathRecipient(deathRecipient_);
316 pasteboardServiceProxy_ = iface_cast<IPasteboardService>(remoteObject);
317 return;
318 }
319 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "remoteObject is null.");
320 sptr<PasteboardLoadCallback> loadCallback = new PasteboardLoadCallback();
321 if (loadCallback == nullptr) {
322 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "loadCallback is nullptr.");
323 return;
324 }
325 int32_t ret = samgrProxy->LoadSystemAbility(PASTEBOARD_SERVICE_ID, loadCallback);
326 if (ret != ERR_OK) {
327 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Failed to load systemAbility.");
328 return;
329 }
330 auto waitStatus = proxyConVar_.wait_for(lock, std::chrono::milliseconds(LOADSA_TIMEOUT_MS),
331 [this]() { return pasteboardServiceProxy_ != nullptr; });
332 if (!waitStatus) {
333 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "Load systemAbility timeout.");
334 return;
335 }
336 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "Getting PasteboardServiceProxy succeeded.");
337 }
338
LoadSystemAbilitySuccess(const sptr<IRemoteObject> & remoteObject)339 void PasteboardClient::LoadSystemAbilitySuccess(const sptr<IRemoteObject> &remoteObject)
340 {
341 std::lock_guard<std::mutex> lock(instanceLock_);
342 if (deathRecipient_ == nullptr) {
343 deathRecipient_ = sptr<IRemoteObject::DeathRecipient>(new PasteboardSaDeathRecipient());
344 }
345 if (remoteObject != nullptr) {
346 remoteObject->AddDeathRecipient(deathRecipient_);
347 pasteboardServiceProxy_ = iface_cast<IPasteboardService>(remoteObject);
348 }
349 proxyConVar_.notify_one();
350 }
351
LoadSystemAbilityFail()352 void PasteboardClient::LoadSystemAbilityFail()
353 {
354 std::lock_guard<std::mutex> lock(instanceLock_);
355 pasteboardServiceProxy_ = nullptr;
356 proxyConVar_.notify_one();
357 }
358
OnRemoteSaDied(const wptr<IRemoteObject> & remote)359 void PasteboardClient::OnRemoteSaDied(const wptr<IRemoteObject> &remote)
360 {
361 PASTEBOARD_HILOGI(PASTEBOARD_MODULE_CLIENT, "OnRemoteSaDied start.");
362 pasteboardServiceProxy_ = nullptr;
363 ConnectService();
364 }
365
PasteboardSaDeathRecipient()366 PasteboardSaDeathRecipient::PasteboardSaDeathRecipient()
367 {
368 }
369
OnRemoteDied(const wptr<IRemoteObject> & object)370 void PasteboardSaDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &object)
371 {
372 PASTEBOARD_HILOGE(PASTEBOARD_MODULE_CLIENT, "PasteboardSaDeathRecipient on remote systemAbility died.");
373 PasteboardClient::GetInstance()->OnRemoteSaDied(object);
374 }
375 } // namespace MiscServices
376 } // namespace OHOS
377