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
16 #include "auto_fill_manager.h"
17
18 #include "auto_fill_error.h"
19 #include "auto_fill_manager_util.h"
20 #include "extension_ability_info.h"
21 #include "ffrt_inner.h"
22 #include "hilog_tag_wrapper.h"
23 #include "parameters.h"
24
25 namespace OHOS {
26 namespace AbilityRuntime {
27 namespace {
28 #ifdef SUPPORT_GRAPHICS
29 const std::string WANT_PARAMS_EXTENSION_TYPE = "autoFill/password";
30 const std::string WANT_PARAMS_SMART_EXTENSION_TYPE = "autoFill/smart";
31 const std::string AUTO_FILL_START_POPUP_WINDOW = "persist.sys.abilityms.autofill.is_passwd_popup_window";
32 constexpr static char WANT_PARAMS_VIEW_DATA_KEY[] = "ohos.ability.params.viewData";
33 constexpr static char WANT_PARAMS_AUTO_FILL_CMD_KEY[] = "ohos.ability.params.autoFillCmd";
34 constexpr static char WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY[] = "ohos.ability.params.popupWindow";
35 constexpr static char WANT_PARAMS_EXTENSION_TYPE_KEY[] = "ability.want.params.uiExtensionType";
36 constexpr static char WANT_PARAMS_AUTO_FILL_TYPE_KEY[] = "ability.want.params.AutoFillType";
37 constexpr static char AUTO_FILL_MANAGER_THREAD[] = "AutoFillManager";
38 constexpr static uint32_t AUTO_FILL_REQUEST_TIME_OUT_VALUE = 1000;
39 constexpr static uint32_t AUTO_FILL_UI_EXTENSION_SESSION_ID_INVALID = 0;
40 constexpr static uint32_t MILL_TO_MICRO = 1000;
41 #endif //SUPPORT_GRAPHICS
42 } // namespace
43 #ifdef SUPPORT_GRAPHICS
GetInstance()44 AutoFillManager &AutoFillManager::GetInstance()
45 {
46 static AutoFillManager instance;
47 return instance;
48 }
49
~AutoFillManager()50 AutoFillManager::~AutoFillManager()
51 {
52 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
53 }
54
RequestAutoFill(Ace::UIContent * uiContent,const AutoFill::AutoFillRequest & request,const std::shared_ptr<IFillRequestCallback> & fillCallback,AutoFill::AutoFillResult & result)55 int32_t AutoFillManager::RequestAutoFill(Ace::UIContent *uiContent, const AutoFill::AutoFillRequest &request,
56 const std::shared_ptr<IFillRequestCallback> &fillCallback, AutoFill::AutoFillResult &result)
57 {
58 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "RequestAutoFill");
59 if (uiContent == nullptr || fillCallback == nullptr) {
60 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null uiContent or fillCallback");
61 return AutoFill::AUTO_FILL_OBJECT_IS_NULL;
62 }
63
64 if (request.autoFillType == AbilityBase::AutoFillType::UNSPECIFIED) {
65 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "autoFillType invalid");
66 return AutoFill::AUTO_FILL_TYPE_INVALID;
67 }
68 return HandleRequestExecuteInner(uiContent, request, fillCallback, nullptr, result);
69 }
70
RequestAutoSave(Ace::UIContent * uiContent,const AutoFill::AutoFillRequest & request,const std::shared_ptr<ISaveRequestCallback> & saveCallback,AutoFill::AutoFillResult & result)71 int32_t AutoFillManager::RequestAutoSave(Ace::UIContent *uiContent, const AutoFill::AutoFillRequest &request,
72 const std::shared_ptr<ISaveRequestCallback> &saveCallback, AutoFill::AutoFillResult &result)
73 {
74 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "RequestAutoSave");
75 if (uiContent == nullptr || saveCallback == nullptr) {
76 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null UIContent or saveCallback");
77 return AutoFill::AUTO_FILL_OBJECT_IS_NULL;
78 }
79 return HandleRequestExecuteInner(uiContent, request, nullptr, saveCallback, result);
80 }
81
HandleRequestExecuteInner(Ace::UIContent * uiContent,const AutoFill::AutoFillRequest & request,const std::shared_ptr<IFillRequestCallback> & fillCallback,const std::shared_ptr<ISaveRequestCallback> & saveCallback,AutoFill::AutoFillResult & result)82 int32_t AutoFillManager::HandleRequestExecuteInner(Ace::UIContent *uiContent, const AutoFill::AutoFillRequest &request,
83 const std::shared_ptr<IFillRequestCallback> &fillCallback,
84 const std::shared_ptr<ISaveRequestCallback> &saveCallback,
85 AutoFill::AutoFillResult &result)
86 {
87 if (uiContent == nullptr || (fillCallback == nullptr && saveCallback == nullptr)) {
88 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null uiContent or fillCallback&saveCallback");
89 return AutoFill::AUTO_FILL_OBJECT_IS_NULL;
90 }
91 if (!IsPreviousRequestFinished(uiContent)) {
92 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "Previous request not finished");
93 return AutoFill::AUTO_FILL_PREVIOUS_REQUEST_NOT_FINISHED;
94 }
95
96 auto extensionCallback = std::make_shared<AutoFillExtensionCallback>();
97 if (fillCallback != nullptr) {
98 extensionCallback->SetFillRequestCallback(fillCallback);
99 } else {
100 extensionCallback->SetSaveRequestCallback(saveCallback);
101 }
102 Ace::ModalUIExtensionCallbacks callback;
103 BindModalUIExtensionCallback(extensionCallback, callback);
104
105 bool isSmartAutoFill = false;
106 AutoFill::AutoFillWindowType autoFillWindowType = AutoFill::AutoFillWindowType::MODAL_WINDOW;
107 if (!ConvertAutoFillWindowType(request, isSmartAutoFill, autoFillWindowType)) {
108 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "Convert auto fill type failed");
109 return AutoFill::AUTO_FILL_CREATE_MODULE_UI_EXTENSION_FAILED;
110 }
111
112 auto callbackId = extensionCallback->GetCallbackId();
113 SetTimeOutEvent(callbackId);
114 result.isPopup = autoFillWindowType == AutoFill::AutoFillWindowType::POPUP_WINDOW ? true : false;
115 auto sessionId = CreateAutoFillExtension(uiContent, request, callback, autoFillWindowType, isSmartAutoFill);
116 if (sessionId == AUTO_FILL_UI_EXTENSION_SESSION_ID_INVALID) {
117 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "Create ui extension failed");
118 RemoveEvent(callbackId);
119 return AutoFill::AUTO_FILL_CREATE_MODULE_UI_EXTENSION_FAILED;
120 }
121 result.autoFillSessionId = callbackId;
122 extensionCallback->SetInstanceId(uiContent->GetInstanceId());
123 extensionCallback->SetSessionId(sessionId);
124 extensionCallback->SetWindowType(autoFillWindowType);
125 extensionCallback->SetExtensionType(isSmartAutoFill);
126 extensionCallback->SetAutoFillRequest(request);
127 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "add callbackId: %{public}u", callbackId);
128 std::lock_guard<std::mutex> lock(extensionCallbacksMutex_);
129 extensionCallbacks_.emplace(callbackId, extensionCallback);
130 return AutoFill::AUTO_FILL_SUCCESS;
131 }
132
UpdateCustomPopupUIExtension(uint32_t autoFillSessionId,const AbilityBase::ViewData & viewData)133 void AutoFillManager::UpdateCustomPopupUIExtension(uint32_t autoFillSessionId, const AbilityBase::ViewData &viewData)
134 {
135 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
136 auto extensionCallback = GetAutoFillExtensionCallback(autoFillSessionId);
137 if (extensionCallback == nullptr) {
138 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null extensionCallback");
139 return;
140 }
141 extensionCallback->UpdateCustomPopupUIExtension(viewData);
142 }
143
CloseUIExtension(uint32_t autoFillSessionId)144 void AutoFillManager::CloseUIExtension(uint32_t autoFillSessionId)
145 {
146 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
147 auto extensionCallback = GetAutoFillExtensionCallback(autoFillSessionId);
148 if (extensionCallback == nullptr) {
149 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null extensionCallback");
150 return;
151 }
152 extensionCallback->CloseUIExtension();
153 }
154
BindModalUIExtensionCallback(const std::shared_ptr<AutoFillExtensionCallback> & extensionCallback,Ace::ModalUIExtensionCallbacks & callback)155 void AutoFillManager::BindModalUIExtensionCallback(
156 const std::shared_ptr<AutoFillExtensionCallback> &extensionCallback, Ace::ModalUIExtensionCallbacks &callback)
157 {
158 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
159 callback.onResult = [extensionCallback](int32_t errCode, const AAFwk::Want& want) {
160 extensionCallback->OnResult(errCode, want);
161 };
162
163 callback.onRelease = [extensionCallback](int arg1) {
164 extensionCallback->OnRelease(arg1);
165 };
166
167 callback.onError = [extensionCallback](int32_t errCode, const std::string& name, const std::string& message) {
168 extensionCallback->OnError(errCode, name, message);
169 };
170
171 callback.onReceive = [extensionCallback](const AAFwk::WantParams &arg1) {
172 extensionCallback->OnReceive(arg1);
173 };
174
175 callback.onRemoteReady = [extensionCallback](const std::shared_ptr<Ace::ModalUIExtensionProxy> &arg1) {
176 extensionCallback->onRemoteReady(arg1);
177 };
178
179 callback.onDestroy = [extensionCallback]() { extensionCallback->onDestroy(); };
180 }
181
CreateAutoFillExtension(Ace::UIContent * uiContent,const AutoFill::AutoFillRequest & request,const Ace::ModalUIExtensionCallbacks & callback,const AutoFill::AutoFillWindowType & autoFillWindowType,bool isSmartAutoFill)182 int32_t AutoFillManager::CreateAutoFillExtension(Ace::UIContent *uiContent,
183 const AutoFill::AutoFillRequest &request,
184 const Ace::ModalUIExtensionCallbacks &callback,
185 const AutoFill::AutoFillWindowType &autoFillWindowType,
186 bool isSmartAutoFill)
187 {
188 int32_t sessionId = AUTO_FILL_UI_EXTENSION_SESSION_ID_INVALID;
189 if (uiContent == nullptr) {
190 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null uiContent");
191 return sessionId;
192 }
193
194 AAFwk::Want want;
195 want.SetParam(WANT_PARAMS_AUTO_FILL_CMD_KEY, static_cast<int32_t>(request.autoFillCommand));
196 want.SetParam(WANT_PARAMS_AUTO_FILL_TYPE_KEY, static_cast<int32_t>(request.autoFillType));
197 want.SetParam(WANT_PARAMS_VIEW_DATA_KEY, request.viewData.ToJsonString());
198 isSmartAutoFill ? want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, WANT_PARAMS_SMART_EXTENSION_TYPE) :
199 want.SetParam(WANT_PARAMS_EXTENSION_TYPE_KEY, WANT_PARAMS_EXTENSION_TYPE);
200
201 if (autoFillWindowType == AutoFill::AutoFillWindowType::POPUP_WINDOW) {
202 want.SetParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, true);
203 Ace::CustomPopupUIExtensionConfig popupConfig;
204 AutoFillManagerUtil::ConvertToPopupUIExtensionConfig(request.config, popupConfig);
205 if (!isSmartAutoFill) {
206 popupConfig.isAutoCancel = false;
207 }
208 sessionId = uiContent->CreateCustomPopupUIExtension(want, callback, popupConfig);
209 } else if (autoFillWindowType == AutoFill::AutoFillWindowType::MODAL_WINDOW) {
210 want.SetParam(WANT_PARAMS_AUTO_FILL_POPUP_WINDOW_KEY, false);
211 Ace::ModalUIExtensionConfig config;
212 config.isAsyncModalBinding = true;
213 config.doAfterAsyncModalBinding = std::move(request.doAfterAsyncModalBinding);
214 sessionId = uiContent->CreateModalUIExtension(want, callback, config);
215 }
216 return sessionId;
217 }
218
IsNeed2SaveRequest(const AbilityBase::ViewData & viewData,bool & isSmartAutoFill)219 bool AutoFillManager::IsNeed2SaveRequest(const AbilityBase::ViewData& viewData, bool& isSmartAutoFill)
220 {
221 bool ret = false;
222 for (auto it = viewData.nodes.begin(); it != viewData.nodes.end(); ++it) {
223 if ((it->autoFillType == AbilityBase::AutoFillType::PASSWORD ||
224 it->autoFillType == AbilityBase::AutoFillType::USER_NAME ||
225 it->autoFillType == AbilityBase::AutoFillType::NEW_PASSWORD) &&
226 it->enableAutoFill && !it->value.empty()) {
227 isSmartAutoFill = false;
228 return true;
229 }
230 if (AbilityBase::AutoFillType::FULL_STREET_ADDRESS <= it->autoFillType &&
231 it->autoFillType <= AbilityBase::AutoFillType::LICENSE_CHASSIS_NUMBER &&
232 it->enableAutoFill && !it->value.empty()) {
233 isSmartAutoFill = true;
234 ret = true;
235 }
236 }
237 return ret;
238 }
239
ConvertAutoFillWindowType(const AutoFill::AutoFillRequest & request,bool & isSmartAutoFill,AutoFill::AutoFillWindowType & autoFillWindowType)240 bool AutoFillManager::ConvertAutoFillWindowType(const AutoFill::AutoFillRequest &request,
241 bool &isSmartAutoFill, AutoFill::AutoFillWindowType &autoFillWindowType)
242 {
243 bool ret = true;
244 autoFillWindowType = AutoFill::AutoFillWindowType::MODAL_WINDOW;
245 AbilityBase::AutoFillType autoFillType = request.autoFillType;
246 if (autoFillType >= AbilityBase::AutoFillType::FULL_STREET_ADDRESS &&
247 autoFillType <= AbilityBase::AutoFillType::LICENSE_CHASSIS_NUMBER) {
248 autoFillWindowType = AutoFill::AutoFillWindowType::POPUP_WINDOW;
249 isSmartAutoFill = true;
250 } else if (autoFillType == AbilityBase::AutoFillType::PASSWORD ||
251 autoFillType == AbilityBase::AutoFillType::USER_NAME ||
252 autoFillType == AbilityBase::AutoFillType::NEW_PASSWORD) {
253 if (system::GetBoolParameter(AUTO_FILL_START_POPUP_WINDOW, false)) {
254 autoFillWindowType = AutoFill::AutoFillWindowType::POPUP_WINDOW;
255 } else {
256 autoFillWindowType = AutoFill::AutoFillWindowType::MODAL_WINDOW;
257 }
258 isSmartAutoFill = false;
259 }
260
261 if (request.autoFillCommand == AutoFill::AutoFillCommand::SAVE) {
262 ret = IsNeed2SaveRequest(request.viewData, isSmartAutoFill);
263 autoFillWindowType = AutoFill::AutoFillWindowType::MODAL_WINDOW;
264 }
265 return ret;
266 }
267
RemoveTask(uint32_t eventId)268 void AutoFillManager::RemoveTask(uint32_t eventId)
269 {
270 std::lock_guard<std::mutex> lock(taskHandlesMutex_);
271 taskHandles_.erase(eventId);
272 }
273
SetTimeOutEvent(uint32_t eventId)274 void AutoFillManager::SetTimeOutEvent(uint32_t eventId)
275 {
276 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "%{public}s called", __func__);
277 auto taskWrap = [ eventId ]() {
278 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "execute HandleTimeout, eventId: %{public}d", eventId);
279 auto extensionCallback = GetInstance().GetAutoFillExtensionCallback(eventId);
280 if (extensionCallback == nullptr) {
281 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null extensionCallback");
282 return;
283 }
284 extensionCallback->HandleTimeOut();
285 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "execute HandleTimeout done, eventId: %{public}d", eventId);
286 AutoFillManager::GetInstance().RemoveTask(eventId);
287 };
288 ffrt::task_attr ffrtTaskAttr;
289 ffrtTaskAttr.delay(AUTO_FILL_REQUEST_TIME_OUT_VALUE * MILL_TO_MICRO);
290 auto ffrtTaskHandle = ffrt::submit_h(std::move(taskWrap), {}, {}, ffrtTaskAttr);
291 if (ffrtTaskHandle == nullptr) {
292 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null ffrtTaskHandle");
293 return;
294 }
295 std::shared_ptr<ffrt::task_handle> taskHandle = std::make_shared<ffrt::task_handle>(
296 std::move(ffrtTaskHandle));
297 std::lock_guard<std::mutex> lock(taskHandlesMutex_);
298 taskHandles_.emplace(eventId, taskHandle);
299 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "%{public}s done", __func__);
300 }
301
RemoveEvent(uint32_t eventId)302 void AutoFillManager::RemoveEvent(uint32_t eventId)
303 {
304 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "%{public}s called", __func__);
305 std::lock_guard<std::mutex> lock(taskHandlesMutex_);
306 auto iter = taskHandles_.find(eventId);
307 if (iter == taskHandles_.end()) {
308 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "not find, eventId: %{public}d", eventId);
309 return;
310 }
311 auto taskHandle = iter->second;
312 if (!taskHandle) {
313 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "null taskHandle");
314 return;
315 }
316 auto ret = ffrt::skip(*taskHandle);
317 if (ret != 0) {
318 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "autofill task skip failed");
319 }
320 taskHandles_.erase(eventId);
321 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "%{public}s done, eventId: %{public}d", __func__, eventId);
322 }
323
IsNeedToCreatePopupWindow(const AbilityBase::AutoFillType & autoFillType)324 bool AutoFillManager::IsNeedToCreatePopupWindow(const AbilityBase::AutoFillType &autoFillType)
325 {
326 TAG_LOGD(AAFwkTag::AUTOFILLMGR, "called");
327 if (autoFillType == AbilityBase::AutoFillType::PASSWORD ||
328 autoFillType == AbilityBase::AutoFillType::USER_NAME ||
329 autoFillType == AbilityBase::AutoFillType::NEW_PASSWORD) {
330 if (system::GetBoolParameter(AUTO_FILL_START_POPUP_WINDOW, false)) {
331 return true;
332 } else {
333 return false;
334 }
335 }
336 return true;
337 }
338
GetAutoFillExtensionCallback(uint32_t callbackId)339 std::shared_ptr<AutoFillExtensionCallback> AutoFillManager::GetAutoFillExtensionCallback(uint32_t callbackId)
340 {
341 std::lock_guard<std::mutex> lock(extensionCallbacksMutex_);
342 auto iter = extensionCallbacks_.find(callbackId);
343 if (iter == extensionCallbacks_.end()) {
344 TAG_LOGE(AAFwkTag::AUTOFILLMGR, "not find, callbackId: %{public}u", callbackId);
345 return nullptr;
346 }
347 return iter->second;
348 }
349
RemoveAutoFillExtensionCallback(uint32_t callbackId)350 void AutoFillManager::RemoveAutoFillExtensionCallback(uint32_t callbackId)
351 {
352 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "remove callbackId: %{public}u", callbackId);
353 std::lock_guard<std::mutex> lock(extensionCallbacksMutex_);
354 extensionCallbacks_.erase(callbackId);
355 }
356
IsPreviousRequestFinished(Ace::UIContent * uiContent)357 bool AutoFillManager::IsPreviousRequestFinished(Ace::UIContent *uiContent)
358 {
359 if (uiContent == nullptr) {
360 return false;
361 }
362 std::lock_guard<std::mutex> lock(extensionCallbacksMutex_);
363 for (const auto& item: extensionCallbacks_) {
364 auto extensionCallback = item.second;
365 if (extensionCallback == nullptr) {
366 continue;
367 }
368 if (extensionCallback->GetWindowType() == AutoFill::AutoFillWindowType::MODAL_WINDOW &&
369 extensionCallback->GetInstanceId() == uiContent->GetInstanceId()) {
370 return false;
371 }
372 if (extensionCallback->GetWindowType() == AutoFill::AutoFillWindowType::POPUP_WINDOW &&
373 extensionCallback->GetInstanceId() == uiContent->GetInstanceId()) {
374 TAG_LOGI(AAFwkTag::AUTOFILLMGR, "autofill popup window exist!");
375 extensionCallback->CloseUIExtension();
376 return true;
377 }
378 }
379 return true;
380 }
381 #endif // SUPPORT_GRAPHICS
382 } // namespace AbilityRuntime
383 } // namespace OHOS
384