!957 【需求】支持系统安全键盘

Merge pull request !957 from mashaoyin/master
This commit is contained in:
openharmony_ci 2023-11-11 10:05:33 +00:00 committed by Gitee
commit 36ba84861f
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
15 changed files with 139 additions and 29 deletions

View File

@ -57,7 +57,6 @@ napi_value JsInputMethodEngineSetting::Init(napi_env env, napi_value exports)
"ENTER_KEY_TYPE_DONE", GetJsConstProperty(env, static_cast<uint32_t>(EnterKeyType::DONE))),
DECLARE_NAPI_PROPERTY(
"ENTER_KEY_TYPE_PREVIOUS", GetJsConstProperty(env, static_cast<uint32_t>(EnterKeyType::PREVIOUS))),
DECLARE_NAPI_PROPERTY("PATTERN_NULL", GetIntJsConstProperty(env, static_cast<int32_t>(TextInputType::NONE))),
DECLARE_NAPI_PROPERTY("PATTERN_TEXT", GetJsConstProperty(env, static_cast<uint32_t>(TextInputType::TEXT))),
DECLARE_NAPI_PROPERTY("PATTERN_NUMBER", GetJsConstProperty(env, static_cast<uint32_t>(TextInputType::NUMBER))),
@ -69,6 +68,10 @@ napi_value JsInputMethodEngineSetting::Init(napi_env env, napi_value exports)
DECLARE_NAPI_PROPERTY("PATTERN_URI", GetJsConstProperty(env, static_cast<uint32_t>(TextInputType::URL))),
DECLARE_NAPI_PROPERTY(
"PATTERN_PASSWORD", GetJsConstProperty(env, static_cast<uint32_t>(TextInputType::VISIBLE_PASSWORD))),
DECLARE_NAPI_PROPERTY("PATTERN_PASSWORD_NUMBER",
GetJsConstProperty(env, static_cast<uint32_t>(TextInputType::NUMBER_PASSWORD))),
DECLARE_NAPI_PROPERTY("PATTERN_PASSWORD_SCREEN_LOCK",
GetJsConstProperty(env, static_cast<uint32_t>(TextInputType::SCREEN_LOCK_PASSWORD))),
DECLARE_NAPI_FUNCTION("getInputMethodEngine", GetInputMethodEngine),
DECLARE_NAPI_FUNCTION("getInputMethodAbility", GetInputMethodAbility),
@ -79,7 +82,6 @@ napi_value JsInputMethodEngineSetting::Init(napi_env env, napi_value exports)
};
NAPI_CALL(
env, napi_define_properties(env, exports, sizeof(descriptor) / sizeof(napi_property_descriptor), descriptor));
napi_property_descriptor properties[] = {
DECLARE_NAPI_FUNCTION("on", Subscribe),
DECLARE_NAPI_FUNCTION("off", UnSubscribe),

View File

@ -45,6 +45,7 @@ napi_value JsPanel::Init(napi_env env)
DECLARE_NAPI_FUNCTION("show", Show),
DECLARE_NAPI_FUNCTION("hide", Hide),
DECLARE_NAPI_FUNCTION("changeFlag", ChangeFlag),
DECLARE_NAPI_FUNCTION("setPrivacyMode", SetPrivacyMode),
DECLARE_NAPI_FUNCTION("on", Subscribe),
DECLARE_NAPI_FUNCTION("off", UnSubscribe),
};
@ -246,6 +247,25 @@ napi_value JsPanel::ChangeFlag(napi_env env, napi_callback_info info)
return nullptr;
}
napi_value JsPanel::SetPrivacyMode(napi_env env, napi_callback_info info)
{
size_t argc = ARGC_MAX;
napi_value argv[ARGC_MAX] = { nullptr };
napi_value thisVar = nullptr;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
PARAM_CHECK_RETURN(env, argc > 0, " should 1 parameter! ", TYPE_NONE, nullptr);
bool isPrivacyMode = false;
// 0 means the first param flag<isPrivacyMode>
napi_status status = JsUtils::GetValue(env, argv[0], isPrivacyMode);
CHECK_RETURN(status == napi_ok, "get isPrivacyMode failed!", nullptr);
auto inputMethodPanel = UnwrapPanel(env, thisVar);
auto ret = inputMethodPanel->SetPrivacyMode(isPrivacyMode);
PARAM_CHECK_RETURN(env, ret != ErrorCode::ERROR_STATUS_PERMISSION_DENIED,
" ohos.permission.PRIVACY_WINDOW permission denied", TYPE_NONE, nullptr);
CHECK_RETURN(ret == ErrorCode::NO_ERROR, "SetPrivacyMode failed!", nullptr);
return nullptr;
}
napi_value JsPanel::Subscribe(napi_env env, napi_callback_info info)
{
IMSA_HILOGD("JsPanel in");

View File

@ -41,6 +41,7 @@ public:
static napi_value Show(napi_env env, napi_callback_info info);
static napi_value Hide(napi_env env, napi_callback_info info);
static napi_value ChangeFlag(napi_env env, napi_callback_info info);
static napi_value SetPrivacyMode(napi_env env, napi_callback_info info);
static napi_value Subscribe(napi_env env, napi_callback_info info);
static napi_value UnSubscribe(napi_env env, napi_callback_info info);
void SetNative(const std::shared_ptr<InputMethodPanel> &panel);

View File

@ -149,6 +149,7 @@ napi_value JsGetInputMethodController::GetJsTextInputTypeProperty(napi_env env)
napi_value typeEmailAddress = nullptr;
napi_value typeUrl = nullptr;
napi_value typeVisiblePassword = nullptr;
napi_value typeNumberPassword = nullptr;
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::NONE), &typeNone));
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::TEXT), &typeText));
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::MULTILINE), &typeMultiline));
@ -158,6 +159,7 @@ napi_value JsGetInputMethodController::GetJsTextInputTypeProperty(napi_env env)
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::EMAIL_ADDRESS), &typeEmailAddress));
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::URL), &typeUrl));
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::VISIBLE_PASSWORD), &typeVisiblePassword));
NAPI_CALL(env, napi_create_int32(env, static_cast<int32_t>(TextInputType::NUMBER_PASSWORD), &typeNumberPassword));
NAPI_CALL(env, napi_create_object(env, &textInputType));
NAPI_CALL(env, napi_set_named_property(env, textInputType, "NONE", typeNone));
NAPI_CALL(env, napi_set_named_property(env, textInputType, "TEXT", typeText));
@ -168,6 +170,7 @@ napi_value JsGetInputMethodController::GetJsTextInputTypeProperty(napi_env env)
NAPI_CALL(env, napi_set_named_property(env, textInputType, "EMAIL_ADDRESS", typeEmailAddress));
NAPI_CALL(env, napi_set_named_property(env, textInputType, "URL", typeUrl));
NAPI_CALL(env, napi_set_named_property(env, textInputType, "VISIBLE_PASSWORD", typeVisiblePassword));
NAPI_CALL(env, napi_set_named_property(env, textInputType, "NUMBER_PASSWORD", typeNumberPassword));
return textInputType;
}

View File

@ -46,6 +46,7 @@ public:
void SetPanelStatusListener(std::shared_ptr<PanelStatusListener> statusListener, const std::string &type);
void ClearPanelListener(const std::string &type);
int32_t SetCallingWindow(uint32_t windowId);
int32_t SetPrivacyMode(bool isPrivacyMode);
bool IsShowing();
int32_t SetTextFieldAvoidInfo(double positionY, double height);
uint32_t windowId_ = 0;

View File

@ -239,6 +239,21 @@ int32_t InputMethodPanel::SetCallingWindow(uint32_t windowId)
return ret == WMError::WM_OK ? ErrorCode::NO_ERROR : ErrorCode::ERROR_OPERATE_PANEL;
}
int32_t InputMethodPanel::SetPrivacyMode(bool isPrivacyMode)
{
IMSA_HILOGI("Run in.");
if (window_ == nullptr) {
IMSA_HILOGE("window_ is nullptr.");
return ErrorCode::ERROR_NULL_POINTER;
}
auto ret = window_->SetPrivacyMode(isPrivacyMode);
if (ret != WMError::WM_OK) {
IMSA_HILOGE("SetWindowPrivacyMode error, ret = %{public}d", ret);
return ErrorCode::ERROR_OPERATE_PANEL;
}
return ErrorCode::NO_ERROR;
}
void InputMethodPanel::PanelStatusChange(const InputWindowStatus &status)
{
if (status == InputWindowStatus::SHOW && showRegistered_ && panelStatusListener_ != nullptr) {

View File

@ -38,6 +38,8 @@ enum class TextInputType {
EMAIL_ADDRESS,
URL,
VISIBLE_PASSWORD,
NUMBER_PASSWORD,
SCREEN_LOCK_PASSWORD,
};
enum class Direction {
@ -93,8 +95,7 @@ struct CursorInfo {
}
};
class KeyEvent {
};
class KeyEvent {};
enum class KeyboardStatus : int32_t { NONE = 0, HIDE, SHOW }; // soft keyboard
@ -160,6 +161,7 @@ struct TextConfig {
enum class InputType {
NONE = -1,
CAMERA_INPUT = 0,
SECURITY_INPUT,
};
} // namespace MiscServices
} // namespace OHOS

View File

@ -25,6 +25,8 @@ namespace MiscServices {
struct InputAttribute {
static const int32_t PATTERN_TEXT = 0x00000001;
static const int32_t PATTERN_PASSWORD = 0x00000007;
static const int32_t PATTERN_PASSWORD_NUMBER = 0x00000008;
static const int32_t PATTERN_PASSWORD_SCREEN_LOCK = 0x00000009;
int32_t inputPattern = 0;
int32_t enterKeyType = 0;
int32_t inputOption = 0;
@ -41,13 +43,14 @@ struct InputAttribute {
bool GetSecurityFlag()
{
return inputPattern == PATTERN_PASSWORD;
return inputPattern == PATTERN_PASSWORD || inputPattern == PATTERN_PASSWORD_SCREEN_LOCK
|| PATTERN_PASSWORD_NUMBER == inputPattern;
}
bool operator==(const InputAttribute &info) const
{
return inputPattern == info.inputPattern && enterKeyType == info.enterKeyType &&
inputOption == info.inputOption;
return inputPattern == info.inputPattern && enterKeyType == info.enterKeyType
&& inputOption == info.inputOption;
}
};
} // namespace MiscServices

View File

@ -67,10 +67,10 @@ bool ImeConfigParse::ParseFromCustomSystem(const std::string &parseKey, T &data)
break;
}
std::string cfgPath(realPath);
if (!GetCfgsFromFile(cfgPath, parseKey, data)) {
if (GetCfgsFromFile(cfgPath, parseKey, data)) {
isSuccess = true;
break;
}
isSuccess = true;
}
FreeCfgFiles(cfgFiles);
IMSA_HILOGI("parse result: %{public}d", isSuccess);

View File

@ -107,7 +107,7 @@ private:
bool IsSwitchPermitted(const SwitchInfo &switchInfo);
bool IsStartInputTypePermitted();
int32_t OnSwitchInputMethod(const SwitchInfo &switchInfo, bool isCheckPermission);
int32_t OnStartInputType(const SwitchInfo &switchInfo);
int32_t OnStartInputType(const SwitchInfo &switchInfo, bool isCheckPermission);
int32_t Switch(const std::string &bundleName, const std::shared_ptr<ImeInfo> &info);
int32_t SwitchExtension(const std::shared_ptr<ImeInfo> &info);
int32_t SwitchSubType(const std::shared_ptr<ImeInfo> &info);
@ -132,6 +132,7 @@ private:
int32_t SwitchType();
int32_t GenerateClientInfo(InputClientInfo &clientInfo);
void RegisterEnableImeObserver();
void CheckSecurityMode(InputClientInfo &inputClientInfo);
std::mutex checkMutex_;
void DatashareCallback(const std::string &key);

View File

@ -51,6 +51,7 @@ public:
bool IsSupported(InputType type);
bool IsInputType(const ImeIdentification &ime);
bool IsStarted();
bool IsCameraImeStarted();
void Set(bool isStarted, const ImeIdentification &currentIme = {});
ImeIdentification GetCurrentIme();
int32_t GetImeByInputType(InputType type, ImeIdentification &ime);

View File

@ -45,6 +45,7 @@
#include "message_handler.h"
#include "panel_info.h"
#include "unRegistered_type.h"
namespace OHOS {
namespace MiscServices {
struct ImeData {
@ -92,6 +93,7 @@ public:
bool IsBoundToClient();
int32_t ExitCurrentInputType();
int32_t IsPanelShown(const PanelInfo &panelInfo, bool &isShown);
bool CheckSecurityMode();
private:
struct ResetManager {

View File

@ -247,6 +247,9 @@ int32_t InputMethodSystemAbility::StartInput(InputClientInfo &inputClientInfo, s
}
}
if (!userSession_->IsProxyImeEnable()) {
CheckSecurityMode(inputClientInfo);
}
int32_t ret = PrepareInput(inputClientInfo);
if (ret != ErrorCode::NO_ERROR) {
IMSA_HILOGE("PrepareInput failed");
@ -255,6 +258,25 @@ int32_t InputMethodSystemAbility::StartInput(InputClientInfo &inputClientInfo, s
return userSession_->OnStartInput(inputClientInfo.client, inputClientInfo.isShowKeyboard, agent);
};
void InputMethodSystemAbility::CheckSecurityMode(InputClientInfo &inputClientInfo)
{
if (inputClientInfo.config.inputAttribute.GetSecurityFlag()) {
if (InputTypeManager::GetInstance().IsStarted()) {
IMSA_HILOGD("security ime has started.");
return;
}
auto ret = StartInputType(InputType::SECURITY_INPUT);
IMSA_HILOGD("switch to security ime ret = %{public}d.", ret);
return;
}
if (!InputTypeManager::GetInstance().IsStarted() || InputTypeManager::GetInstance().IsCameraImeStarted()) {
IMSA_HILOGD("security ime is not start or camera ime started, keep current.");
return;
}
auto ret = StartInputType(InputType::NONE);
IMSA_HILOGD("Exit security ime ret = %{public}d.", ret);
}
int32_t InputMethodSystemAbility::ShowInput(sptr<IInputClient> client)
{
AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
@ -384,15 +406,22 @@ bool InputMethodSystemAbility::IsInputTypeSupported(InputType type)
int32_t InputMethodSystemAbility::StartInputType(InputType type)
{
ImeIdentification ime;
int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
if (ret != ErrorCode::NO_ERROR) {
return ret;
if (type != InputType::NONE) {
ImeIdentification ime;
int32_t ret = InputTypeManager::GetInstance().GetImeByInputType(type, ime);
if (ret != ErrorCode::NO_ERROR) {
return ret;
}
SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
switchQueue_.Push(switchInfo);
IMSA_HILOGI("start input type: %{public}d", type);
return type == InputType::SECURITY_INPUT ? OnStartInputType(switchInfo, false)
: OnStartInputType(switchInfo, true);
}
SwitchInfo switchInfo = { std::chrono::system_clock::now(), ime.bundleName, ime.subName };
auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
SwitchInfo switchInfo = { std::chrono::system_clock::now(), cfgIme->bundleName, cfgIme->subName };
switchQueue_.Push(switchInfo);
IMSA_HILOGI("start input type: %{public}d", type);
return OnStartInputType(switchInfo);
return OnStartInputType(switchInfo, false);
}
int32_t InputMethodSystemAbility::ExitCurrentInputType()
@ -405,6 +434,9 @@ int32_t InputMethodSystemAbility::ExitCurrentInputType()
if (!identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), defaultIme->prop.name)) {
return ErrorCode::ERROR_NOT_DEFAULT_IME;
}
if (userSession_->CheckSecurityMode()) {
return StartInputType(InputType::SECURITY_INPUT);
}
return userSession_->ExitCurrentInputType();
}
@ -435,8 +467,9 @@ int32_t InputMethodSystemAbility::SwitchInputMethod(const std::string &bundleNam
}
switchInfo.timestamp = std::chrono::system_clock::now();
switchQueue_.Push(switchInfo);
return InputTypeManager::GetInstance().IsInputType({ bundleName, subName }) ? OnStartInputType(switchInfo)
: OnSwitchInputMethod(switchInfo, true);
return InputTypeManager::GetInstance().IsInputType({ bundleName, subName })
? OnStartInputType(switchInfo, true)
: OnSwitchInputMethod(switchInfo, true);
}
int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchInfo, bool isCheckPermission)
@ -474,15 +507,22 @@ int32_t InputMethodSystemAbility::OnSwitchInputMethod(const SwitchInfo &switchIn
return ret;
}
int32_t InputMethodSystemAbility::OnStartInputType(const SwitchInfo &switchInfo)
int32_t InputMethodSystemAbility::OnStartInputType(const SwitchInfo &switchInfo, bool isCheckPermission)
{
if (!switchQueue_.IsReady(switchInfo)) {
IMSA_HILOGD("start wait");
switchQueue_.Wait(switchInfo);
usleep(SWITCH_BLOCK_TIME);
}
auto cfgIme = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_);
if (switchInfo.bundleName == cfgIme->bundleName && switchInfo.subName == cfgIme->subName) {
IMSA_HILOGD("start input type is current ime, exit input type.");
int32_t ret = userSession_->ExitCurrentInputType();
switchQueue_.Pop();
return ret;
}
IMSA_HILOGD("start switch %{public}s|%{public}s", switchInfo.bundleName.c_str(), switchInfo.subName.c_str());
if (!IsStartInputTypePermitted()) {
if (isCheckPermission && !IsStartInputTypePermitted()) {
IMSA_HILOGE("not permitted to start input type");
switchQueue_.Pop();
return ErrorCode::ERROR_STATUS_PERMISSION_DENIED;
@ -553,7 +593,10 @@ int32_t InputMethodSystemAbility::SwitchSubType(const std::shared_ptr<ImeInfo> &
int32_t InputMethodSystemAbility::SwitchInputType(const SwitchInfo &switchInfo)
{
auto currentImeBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
if (switchInfo.bundleName == currentImeBundleName) {
bool checkSameIme = InputTypeManager::GetInstance().IsStarted()
? switchInfo.bundleName == InputTypeManager::GetInstance().GetCurrentIme().bundleName
: switchInfo.bundleName == currentImeBundleName;
if (checkSameIme) {
IMSA_HILOGD("only need to switch subtype: %{public}s", switchInfo.subName.c_str());
auto ret = userSession_->SwitchSubtype({ .name = switchInfo.bundleName, .id = switchInfo.subName });
if (ret == ErrorCode::NO_ERROR) {
@ -948,9 +991,9 @@ bool InputMethodSystemAbility::IsSwitchPermitted(const SwitchInfo &switchInfo)
{
auto currentBundleName = ImeCfgManager::GetInstance().GetCurrentImeCfg(userId_)->bundleName;
// if currentIme is switching subtype, permission verification is not performed.
if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY) ||
(identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName) &&
!switchInfo.subName.empty())) {
if (identityChecker_->HasPermission(IPCSkeleton::GetCallingTokenID(), PERMISSION_CONNECT_IME_ABILITY)
|| (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), currentBundleName)
&& !switchInfo.subName.empty())) {
return true;
}
InputMethodSysEvent::GetInstance().InputmethodFaultReporter(
@ -969,7 +1012,7 @@ bool InputMethodSystemAbility::IsStartInputTypePermitted()
if (identityChecker_->IsBundleNameValid(IPCSkeleton::GetCallingTokenID(), defaultIme->prop.name)) {
return true;
}
if (!InputTypeManager::GetInstance().IsStarted()) {
if (!InputTypeManager::GetInstance().IsCameraImeStarted()) {
return identityChecker_->IsFocused(IPCSkeleton::GetCallingPid(), IPCSkeleton::GetCallingUid())
&& userSession_->IsBoundToClient();
}

View File

@ -119,6 +119,13 @@ bool InputTypeManager::IsStarted()
return isStarted_;
}
bool InputTypeManager::IsCameraImeStarted()
{
std::lock_guard<std::mutex> lock(stateLock_);
return isStarted_ && inputTypes_.find(InputType::CAMERA_INPUT) != inputTypes_.end()
&& inputTypes_[InputType::CAMERA_INPUT] == currentTypeIme_;
}
ImeIdentification InputTypeManager::GetCurrentIme()
{
std::lock_guard<std::mutex> lock(stateLock_);

View File

@ -723,9 +723,8 @@ void PerUserSession::OnUnfocused(int32_t pid, int32_t uid)
if (clientInfo != nullptr) {
if (clientInfo->isAttaching) {
std::unique_lock<std::mutex> lock(attachLock_);
imeAttachCv_.wait_for(lock, std::chrono::milliseconds(IME_ATTACH_INTERVAL), [&clientInfo]() {
return !clientInfo->isAttaching;
});
imeAttachCv_.wait_for(lock, std::chrono::milliseconds(IME_ATTACH_INTERVAL),
[&clientInfo]() { return !clientInfo->isAttaching; });
}
RemoveClient(clientInfo->client);
InputMethodSysEvent::GetInstance().OperateSoftkeyboardBehaviour(OperateIMEInfoCode::IME_HIDE_UNFOCUSED);
@ -935,5 +934,15 @@ int32_t PerUserSession::IsPanelShown(const PanelInfo &panelInfo, bool &isShown)
}
return ime->core->IsPanelShown(panelInfo, isShown);
}
bool PerUserSession::CheckSecurityMode()
{
auto client = GetCurrentClient();
auto clientInfo = client != nullptr ? GetClientInfo(client->AsObject()) : nullptr;
if (clientInfo != nullptr) {
return clientInfo->config.inputAttribute.GetSecurityFlag();
}
return false;
}
} // namespace MiscServices
} // namespace OHOS