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