1 /*
2  * Copyright (c) 2023-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 #include "auto_fill_extension_callback.h"
16 
17 #include "auto_fill_error.h"
18 #include "auto_fill_manager.h"
19 #include "auto_fill_manager_util.h"
20 #include "hilog_tag_wrapper.h"
21 #include "int_wrapper.h"
22 #include "string_wrapper.h"
23 #include "view_data.h"
24 
25 namespace OHOS {
26 namespace AbilityRuntime {
27 namespace {
28 constexpr const char* WANT_PARAMS_VIEW_DATA_KEY = "ohos.ability.params.viewData";
29 constexpr const char* WANT_PARAMS_AUTO_FILL_CMD_KEY = "ohos.ability.params.autoFillCmd";
30 constexpr const char* WANT_PARAMS_FILL_CONTENT = "ohos.ability.params.fillContent";
31 constexpr const char* WANT_PARAMS_CUSTOM_DATA_KEY = "ohos.ability.params.customData";
32 constexpr const char* WANT_PARAMS_AUTO_FILL_EVENT_KEY = "ability.want.params.AutoFillEvent";
33 constexpr const char* WANT_PARAMS_UPDATE_POPUP_WIDTH = "ohos.ability.params.popupWidth";
34 constexpr const char* WANT_PARAMS_UPDATE_POPUP_HEIGHT = "ohos.ability.params.popupHeight";
35 constexpr const char* WANT_PARAMS_UPDATE_POPUP_PLACEMENT = "ohos.ability.params.popupPlacement";
36 constexpr const char* WANT_PARAMS_EXTENSION_TYPE_KEY = "ability.want.params.uiExtensionType";
37 constexpr const char* WANT_PARAMS_EXTENSION_TYPE = "autoFill/password";
38 constexpr const char* WANT_PARAMS_SMART_EXTENSION_TYPE = "autoFill/smart";
39 constexpr const char* WANT_PARAMS_AUTO_FILL_TYPE_KEY = "ability.want.params.AutoFillType";
40 constexpr const char* WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY = "ohos.ability.params.popupWindow";
41 } // namespace
42 
AutoFillExtensionCallback()43 AutoFillExtensionCallback::AutoFillExtensionCallback()
44 {
45     callbackId_ = GenerateCallbackId();
46 }
47 
OnResult(int32_t errCode,const AAFwk::Want & want)48 void AutoFillExtensionCallback::OnResult(int32_t errCode, const AAFwk::Want &want)
49 {
50     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "Called, result code: %{public}d", errCode);
51     AutoFillManager::GetInstance().RemoveEvent(callbackId_);
52     CloseUIExtension();
53     if (autoFillWindowType_ == AutoFill::AutoFillWindowType::POPUP_WINDOW) {
54         isOnResult_ = true;
55         want_ = want;
56         errCode_ = errCode;
57         return;
58     }
59 
60     if (errCode == AutoFill::AUTO_FILL_SUCCESS) {
61         SendAutoFillSuccess(want);
62     } else {
63         auto resultCode = (errCode == AutoFill::AUTO_FILL_CANCEL) ?
64             AutoFill::AUTO_FILL_CANCEL : AutoFill::AUTO_FILL_FAILED;
65         SendAutoFillFailed(resultCode, want);
66     }
67 }
68 
OnRelease(int32_t errCode)69 void AutoFillExtensionCallback::OnRelease(int32_t errCode)
70 {
71     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "Called, result code: %{public}d", errCode);
72     AutoFillManager::GetInstance().RemoveEvent(callbackId_);
73     CloseUIExtension();
74     if (errCode != 0) {
75         SendAutoFillFailed(AutoFill::AUTO_FILL_RELEASE_FAILED);
76     }
77 }
78 
OnError(int32_t errCode,const std::string & name,const std::string & message)79 void AutoFillExtensionCallback::OnError(int32_t errCode, const std::string &name, const std::string &message)
80 {
81     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "Called, errcode: %{public}d, name: %{public}s, message: %{public}s",
82         errCode, name.c_str(), message.c_str());
83     AutoFillManager::GetInstance().RemoveEvent(callbackId_);
84     CloseUIExtension();
85     if (errCode != 0) {
86         SendAutoFillFailed(AutoFill::AUTO_FILL_ON_ERROR);
87     }
88 }
89 
HandleReloadInModal(const AAFwk::WantParams & wantParams)90 void AutoFillExtensionCallback::HandleReloadInModal(const AAFwk::WantParams &wantParams)
91 {
92     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
93     SetModalUIExtensionProxy(nullptr);
94 
95     auto oldWindowType = autoFillWindowType_;
96     auto oldSessionId = sessionId_;
97     int32_t resultCode = ReloadInModal(wantParams);
98     if (resultCode != AutoFill::AUTO_FILL_SUCCESS) {
99         SendAutoFillFailed(resultCode);
100     }
101 
102     auto uiContent = GetUIContent();
103     if (uiContent == nullptr) {
104         TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null uiContent");
105         return;
106     }
107 
108     if (oldWindowType == AutoFill::AutoFillWindowType::POPUP_WINDOW) {
109         isReloadInModal_ = true;
110         uiContent->DestroyCustomPopupUIExtension(oldSessionId);
111     } else {
112         TAG_LOGW(AAFwkTag::AUTOFILLMGR, "Window type not popup, can not be destroyed");
113     }
114 }
115 
ReloadInModal(const AAFwk::WantParams & wantParams)116 int32_t AutoFillExtensionCallback::ReloadInModal(const AAFwk::WantParams &wantParams)
117 {
118     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
119     std::lock_guard<std::mutex> lock(closeMutex_);
120     auto uiContent = GetUIContent();
121     if (uiContent == nullptr) {
122         TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null uiContent");
123         return AutoFill::AUTO_FILL_OBJECT_IS_NULL;
124     }
125 
126     AutoFillManager::GetInstance().SetTimeOutEvent(callbackId_);
127     AAFwk::Want want;
128     want.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, static_cast<int32_t>(AutoFill::AutoFillCommand::RELOAD_IN_MODAL));
129     want.SetParam(WANT_PARAMS_CUSTOM_DATA_KEY, wantParams.GetStringParam(WANT_PARAMS_CUSTOM_DATA_KEY));
130     isSmartAutoFill_ ? want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, std::string(WANT_PARAMS_SMART_EXTENSION_TYPE)) :
131         want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, std::string(WANT_PARAMS_EXTENSION_TYPE));
132     want.SetParam(WANT_PARAMS_AUTO_FILL_TYPE_KEY, static_cast<int32_t>(request_.autoFillType));
133     want.SetParam(WANT_PARAMS_VIEW_DATA_KEY, request_.viewData.ToJsonString());
134     want.SetParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, false);
135     Ace::ModalUIExtensionCallbacks callback;
136     AutoFillManager::GetInstance().BindModalUIExtensionCallback(shared_from_this(), callback);
137     Ace::ModalUIExtensionConfig config;
138     config.isAsyncModalBinding = true;
139     int32_t sessionId = 0;
140     sessionId = uiContent->CreateModalUIExtension(want, callback, config);
141     if (sessionId == 0) {
142         TAG_LOGE(AAFwkTag::AUTOFILLMGR, "Create ui extension failed");
143         AutoFillManager::GetInstance().RemoveEvent(callbackId_);
144         return AutoFill::AUTO_FILL_CREATE_MODULE_UI_EXTENSION_FAILED;
145     }
146     SetSessionId(sessionId);
147     SetWindowType(AutoFill::AutoFillWindowType::MODAL_WINDOW);
148     return AutoFill::AUTO_FILL_SUCCESS;
149 }
150 
OnReceive(const AAFwk::WantParams & wantParams)151 void AutoFillExtensionCallback::OnReceive(const AAFwk::WantParams &wantParams)
152 {
153     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
154     int32_t cmdValue = wantParams.GetIntParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, 0);
155     if (cmdValue == static_cast<int32_t>(AutoFill::AutoFillCommand::RELOAD_IN_MODAL)) {
156         HandleReloadInModal(wantParams);
157         return;
158     } else if (cmdValue == static_cast<int32_t>(AutoFill::AutoFillCommand::RESIZE)) {
159         UpdateCustomPopupConfig(wantParams);
160     }
161     if (wantParams.GetIntParam(WANT_PARAMS_AUTO_FILL_EVENT_KEY, 0) == AutoFill::AUTO_FILL_CANCEL_TIME_OUT) {
162         AutoFillManager::GetInstance().RemoveEvent(callbackId_);
163     }
164 }
165 
UpdateCustomPopupConfig(const AAFwk::WantParams & wantParams)166 void AutoFillExtensionCallback::UpdateCustomPopupConfig(const AAFwk::WantParams &wantParams)
167 {
168     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
169     AutoFill::AutoFillCustomConfig autoFillCustomConfig = request_.config;
170     if (wantParams.HasParam(WANT_PARAMS_UPDATE_POPUP_WIDTH) &&
171         wantParams.HasParam(WANT_PARAMS_UPDATE_POPUP_HEIGHT)) {
172         AutoFill::PopupSize popupSize;
173         popupSize.width = wantParams.GetIntParam(WANT_PARAMS_UPDATE_POPUP_WIDTH, 0);
174         popupSize.height = wantParams.GetIntParam(WANT_PARAMS_UPDATE_POPUP_HEIGHT, 0);
175         autoFillCustomConfig.targetSize = popupSize;
176     }
177     if (wantParams.HasParam(WANT_PARAMS_UPDATE_POPUP_PLACEMENT)) {
178         autoFillCustomConfig.placement =
179             static_cast<AutoFill::PopupPlacement>(wantParams.GetIntParam(WANT_PARAMS_UPDATE_POPUP_PLACEMENT, 0));
180     }
181     {
182         std::lock_guard<std::mutex> lock(requestCallbackMutex_);
183         if (fillCallback_ != nullptr) {
184             fillCallback_->onPopupConfigWillUpdate(autoFillCustomConfig);
185         }
186     }
187     Ace::CustomPopupUIExtensionConfig popupConfig;
188     AutoFillManagerUtil::ConvertToPopupUIExtensionConfig(autoFillCustomConfig, popupConfig);
189     auto uiContent = GetUIContent();
190     if (uiContent == nullptr) {
191         TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null uiContent");
192         return;
193     }
194     uiContent->UpdateCustomPopupUIExtension(popupConfig);
195 }
196 
onRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> & modalUIExtensionProxy)197 void AutoFillExtensionCallback::onRemoteReady(const std::shared_ptr<Ace::ModalUIExtensionProxy> &modalUIExtensionProxy)
198 {
199     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
200     if (modalUIExtensionProxy == nullptr) {
201         TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null proxy");
202         return;
203     }
204     SetModalUIExtensionProxy(modalUIExtensionProxy);
205     if (request_.onUIExtensionProxyReady) {
206         request_.onUIExtensionProxyReady();
207     }
208 }
209 
onDestroy()210 void AutoFillExtensionCallback::onDestroy()
211 {
212     TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
213     if (isReloadInModal_) {
214         isReloadInModal_ = false;
215         return;
216     }
217     if (isOnResult_ && autoFillWindowType_ == AutoFill::AutoFillWindowType::POPUP_WINDOW) {
218         isOnResult_ = false;
219         if (errCode_ == AutoFill::AUTO_FILL_SUCCESS) {
220             SendAutoFillSuccess(want_);
221         } else {
222             auto resultCode = (errCode_ == AutoFill::AUTO_FILL_CANCEL) ?
223                 AutoFill::AUTO_FILL_CANCEL : AutoFill::AUTO_FILL_FAILED;
224             SendAutoFillFailed(resultCode);
225         }
226         return;
227     }
228     CloseUIExtension();
229     SendAutoFillFailed(AutoFill::AUTO_FILL_FAILED);
230 }
231 
SetFillRequestCallback(const std::shared_ptr<IFillRequestCallback> & callback)232 void AutoFillExtensionCallback::SetFillRequestCallback(const std::shared_ptr<IFillRequestCallback> &callback)
233 {
234     std::lock_guard<std::mutex> lock(requestCallbackMutex_);
235     fillCallback_ = callback;
236 }
237 
SetSaveRequestCallback(const std::shared_ptr<ISaveRequestCallback> & callback)238 void AutoFillExtensionCallback::SetSaveRequestCallback(const std::shared_ptr<ISaveRequestCallback> &callback)
239 {
240     std::lock_guard<std::mutex> lock(requestCallbackMutex_);
241     saveCallback_ = callback;
242 }
243 
SetSessionId(int32_t sessionId)244 void AutoFillExtensionCallback::SetSessionId(int32_t sessionId)
245 {
246     sessionId_= sessionId;
247 }
248 
SetInstanceId(int32_t instanceId)249 void AutoFillExtensionCallback::SetInstanceId(int32_t instanceId)
250 {
251     instanceId_.store(instanceId);
252 }
253 
GetInstanceId()254 int32_t AutoFillExtensionCallback::GetInstanceId()
255 {
256     return instanceId_.load();
257 }
258 
GetUIContent()259 Ace::UIContent* AutoFillExtensionCallback::GetUIContent()
260 {
261     return Ace::UIContent::GetUIContent(GetInstanceId());
262 }
263 
SetWindowType(const AutoFill::AutoFillWindowType & autoFillWindowType)264 void AutoFillExtensionCallback::SetWindowType(const AutoFill::AutoFillWindowType &autoFillWindowType)
265 {
266     autoFillWindowType_ = autoFillWindowType;
267 }
268 
GetWindowType() const269 AutoFill::AutoFillWindowType AutoFillExtensionCallback::GetWindowType() const
270 {
271     return autoFillWindowType_;
272 }
273 
SetAutoFillRequest(const AutoFill::AutoFillRequest & request)274 void AutoFillExtensionCallback::SetAutoFillRequest(const AutoFill::AutoFillRequest &request)
275 {
276     request_ = request;
277 }
278 
SetExtensionType(bool isSmartAutoFill)279 void AutoFillExtensionCallback::SetExtensionType(bool isSmartAutoFill)
280 {
281     isSmartAutoFill_ = isSmartAutoFill;
282 }
283 
HandleTimeOut()284 void AutoFillExtensionCallback::HandleTimeOut()
285 {
286     CloseUIExtension();
287     SendAutoFillFailed(AutoFill::AUTO_FILL_REQUEST_TIME_OUT);
288 }
289 
GenerateCallbackId()290 uint32_t AutoFillExtensionCallback::GenerateCallbackId()
291 {
292     static std::atomic<uint32_t> callbackId(0);
293     ++callbackId;
294     return callbackId.load();
295 }
296 
GetCallbackId() const297 uint32_t AutoFillExtensionCallback::GetCallbackId() const
298 {
299     return callbackId_;
300 }
301 
SetModalUIExtensionProxy(const std::shared_ptr<Ace::ModalUIExtensionProxy> & proxy)302 void AutoFillExtensionCallback::SetModalUIExtensionProxy(const std::shared_ptr<Ace::ModalUIExtensionProxy>& proxy)
303 {
304     std::lock_guard<std::mutex> lock(proxyMutex_);
305     modalUIExtensionProxy_ = proxy;
306 }
307 
GetModalUIExtensionProxy()308 std::shared_ptr<Ace::ModalUIExtensionProxy> AutoFillExtensionCallback::GetModalUIExtensionProxy()
309 {
310     std::lock_guard<std::mutex> lock(proxyMutex_);
311     return modalUIExtensionProxy_;
312 }
313 
UpdateCustomPopupUIExtension(const AbilityBase::ViewData & viewData)314 void AutoFillExtensionCallback::UpdateCustomPopupUIExtension(const AbilityBase::ViewData &viewData)
315 {
316     auto modalUIExtensionProxy = GetModalUIExtensionProxy();
317     if (modalUIExtensionProxy == nullptr) {
318         TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null UIExtensionProxy");
319         return;
320     }
321     AAFwk::WantParams wantParams;
322     wantParams.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY,
323         AAFwk::Integer::Box(static_cast<int32_t>(AutoFill::AutoFillCommand::UPDATE)));
324     wantParams.SetParam(WANT_PARAMS_VIEW_DATA_KEY, AAFwk::String::Box(viewData.ToJsonString()));
325     modalUIExtensionProxy->SendData(wantParams);
326 }
327 
SendAutoFillSuccess(const AAFwk::Want & want)328 void AutoFillExtensionCallback::SendAutoFillSuccess(const AAFwk::Want &want)
329 {
330     TAG_LOGI(AAFwkTag::AUTOFILLMGR, "called");
331     std::lock_guard<std::mutex> lock(requestCallbackMutex_);
332     if (fillCallback_ != nullptr) {
333         std::string dataStr = want.GetStringParam(WANT_PARAMS_VIEW_DATA_KEY);
334         AbilityBase::ViewData viewData;
335         viewData.FromJsonString(dataStr.c_str());
336         fillCallback_->OnFillRequestSuccess(viewData);
337         fillCallback_ = nullptr;
338     }
339 
340     if (saveCallback_ != nullptr) {
341         saveCallback_->OnSaveRequestSuccess();
342         saveCallback_ = nullptr;
343     }
344     AutoFillManager::GetInstance().RemoveAutoFillExtensionCallback(callbackId_);
345 }
346 
SendAutoFillFailed(int32_t errCode,const AAFwk::Want & want)347 void AutoFillExtensionCallback::SendAutoFillFailed(int32_t errCode, const AAFwk::Want &want)
348 {
349     TAG_LOGI(AAFwkTag::AUTOFILLMGR, "called");
350     std::lock_guard<std::mutex> lock(requestCallbackMutex_);
351     if (fillCallback_ != nullptr) {
352         std::string fillContent = want.GetStringParam(WANT_PARAMS_FILL_CONTENT);
353         bool isPopup = (autoFillWindowType_ == AutoFill::AutoFillWindowType::POPUP_WINDOW);
354         fillCallback_->OnFillRequestFailed(errCode, fillContent, isPopup);
355         fillCallback_ = nullptr;
356     }
357 
358     if (saveCallback_ != nullptr) {
359         saveCallback_->OnSaveRequestFailed();
360         saveCallback_ = nullptr;
361     }
362     AutoFillManager::GetInstance().RemoveAutoFillExtensionCallback(callbackId_);
363 }
364 
CloseUIExtension()365 void AutoFillExtensionCallback::CloseUIExtension()
366 {
367     Ace::UIContent* uiContent = nullptr;
368     {
369         std::lock_guard<std::mutex> lock(closeMutex_);
370         uiContent = GetUIContent();
371         if (uiContent == nullptr) {
372             TAG_LOGD(AAFwkTag::AUTOFILLMGR, "null uiContent");
373             return;
374         }
375         SetInstanceId(-1);
376     }
377 
378     if (autoFillWindowType_ == AutoFill::AutoFillWindowType::POPUP_WINDOW) {
379         uiContent->DestroyCustomPopupUIExtension(sessionId_);
380     } else if (autoFillWindowType_ == AutoFill::AutoFillWindowType::MODAL_WINDOW) {
381         uiContent->CloseModalUIExtension(sessionId_);
382     }
383     SetModalUIExtensionProxy(nullptr);
384 }
385 } // namespace AbilityRuntime
386 } // namespace OHOS
387