1 /*
2 * Copyright (c) 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 "input_method_controller.h"
16 #include "native_message_handler_callback.h"
17 #include "native_inputmethod_types.h"
18 #include "native_inputmethod_utils.h"
19 #include "string_ex.h"
20 #ifdef __cplusplus
21 extern "C" {
22 #endif /* __cplusplus */
23 using namespace OHOS;
24 using namespace OHOS::MiscServices;
25 constexpr size_t INVALID_MSG_ID_SIZE = 256; // 256B
26 constexpr size_t INVALID_MSG_PARAM_SIZE = 128 * 1024; // 128KB
IsValidMessageHandlerProxy(InputMethod_MessageHandlerProxy * messageHandler)27 static int32_t IsValidMessageHandlerProxy(InputMethod_MessageHandlerProxy *messageHandler)
28 {
29 if (messageHandler == nullptr) {
30 IMSA_HILOGE("messageHandler is nullptr");
31 return IME_ERR_OK;
32 }
33 if (messageHandler->onTerminatedFunc == nullptr) {
34 IMSA_HILOGE("onTerminatedFunc is nullptr");
35 return IME_ERR_NULL_POINTER;
36 }
37 if (messageHandler->onMessageFunc == nullptr) {
38 IMSA_HILOGE("onMessageFunc is nullptr");
39 return IME_ERR_NULL_POINTER;
40 }
41 return IME_ERR_OK;
42 }
43
OH_InputMethodProxy_ShowKeyboard(InputMethod_InputMethodProxy * inputMethodProxy)44 InputMethod_ErrorCode OH_InputMethodProxy_ShowKeyboard(InputMethod_InputMethodProxy *inputMethodProxy)
45 {
46 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
47 if (errCode != IME_ERR_OK) {
48 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
49 return errCode;
50 }
51 auto instance = InputMethodController::GetInstance();
52 if (instance == nullptr) {
53 IMSA_HILOGE("InputMethodController is nullptr");
54 return IME_ERR_NULL_POINTER;
55 }
56 return ErrorCodeConvert(instance->ShowCurrentInput());
57 }
58
OH_InputMethodProxy_ShowTextInput(InputMethod_InputMethodProxy * inputMethodProxy,InputMethod_AttachOptions * options)59 InputMethod_ErrorCode OH_InputMethodProxy_ShowTextInput(
60 InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_AttachOptions *options)
61 {
62 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
63 if (errCode != IME_ERR_OK || options == nullptr) {
64 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
65 return errCode;
66 }
67 AttachOptions attachOptions;
68 attachOptions.isShowKeyboard = options->showKeyboard;
69 attachOptions.requestKeyboardReason =
70 static_cast<RequestKeyboardReason>(static_cast<int32_t>(options->requestKeyboardReason));
71 auto instance = InputMethodController::GetInstance();
72 if (instance == nullptr) {
73 IMSA_HILOGE("InputMethodController is nullptr");
74 return IME_ERR_NULL_POINTER;
75 }
76 return ErrorCodeConvert(instance->ShowTextInput(attachOptions));
77 }
78
OH_InputMethodProxy_HideKeyboard(InputMethod_InputMethodProxy * inputMethodProxy)79 InputMethod_ErrorCode OH_InputMethodProxy_HideKeyboard(InputMethod_InputMethodProxy *inputMethodProxy)
80 {
81 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
82 if (errCode != IME_ERR_OK) {
83 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
84 return errCode;
85 }
86 auto instance = InputMethodController::GetInstance();
87 if (instance == nullptr) {
88 IMSA_HILOGE("InputMethodController is nullptr");
89 return IME_ERR_NULL_POINTER;
90 }
91 return ErrorCodeConvert(instance->HideCurrentInput());
92 }
OH_InputMethodProxy_NotifySelectionChange(InputMethod_InputMethodProxy * inputMethodProxy,char16_t text[],size_t length,int start,int end)93 InputMethod_ErrorCode OH_InputMethodProxy_NotifySelectionChange(
94 InputMethod_InputMethodProxy *inputMethodProxy, char16_t text[], size_t length, int start, int end)
95 {
96 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
97 if (errCode != IME_ERR_OK) {
98 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
99 return errCode;
100 }
101 if (text == nullptr) {
102 IMSA_HILOGE("text is nullptr");
103 return IME_ERR_NULL_POINTER;
104 }
105
106 if (length > MAX_TEXT_LENGTH) {
107 IMSA_HILOGE("text length is too long length=%{public}zu", length);
108 return IME_ERR_PARAMCHECK;
109 }
110 auto instance = InputMethodController::GetInstance();
111 if (instance == nullptr) {
112 IMSA_HILOGE("InputMethodController is nullptr");
113 return IME_ERR_NULL_POINTER;
114 }
115 return ErrorCodeConvert(instance->OnSelectionChange(std::u16string(text, length), start, end));
116 }
OH_InputMethodProxy_NotifyConfigurationChange(InputMethod_InputMethodProxy * inputMethodProxy,InputMethod_EnterKeyType enterKey,InputMethod_TextInputType textType)117 InputMethod_ErrorCode OH_InputMethodProxy_NotifyConfigurationChange(InputMethod_InputMethodProxy *inputMethodProxy,
118 InputMethod_EnterKeyType enterKey, InputMethod_TextInputType textType)
119 {
120 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
121 if (errCode != IME_ERR_OK) {
122 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
123 return errCode;
124 }
125 Configuration info;
126 info.SetEnterKeyType(static_cast<EnterKeyType>(enterKey));
127 info.SetTextInputType(static_cast<TextInputType>(textType));
128 auto instance = InputMethodController::GetInstance();
129 if (instance == nullptr) {
130 IMSA_HILOGE("InputMethodController is nullptr");
131 return IME_ERR_NULL_POINTER;
132 }
133 return ErrorCodeConvert(instance->OnConfigurationChange(info));
134 }
135
OH_InputMethodProxy_NotifyCursorUpdate(InputMethod_InputMethodProxy * inputMethodProxy,InputMethod_CursorInfo * cursorInfo)136 InputMethod_ErrorCode OH_InputMethodProxy_NotifyCursorUpdate(
137 InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_CursorInfo *cursorInfo)
138 {
139 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
140 if (errCode != IME_ERR_OK) {
141 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
142 return errCode;
143 }
144 if (cursorInfo == nullptr) {
145 IMSA_HILOGE("cursorInfo is nullptr");
146 return IME_ERR_NULL_POINTER;
147 }
148 CursorInfo info;
149 info.left = cursorInfo->left;
150 info.top = cursorInfo->top;
151 info.width = cursorInfo->width;
152 info.height = cursorInfo->height;
153 auto instance = InputMethodController::GetInstance();
154 if (instance == nullptr) {
155 IMSA_HILOGE("InputMethodController is nullptr");
156 return IME_ERR_NULL_POINTER;
157 }
158 return ErrorCodeConvert(instance->OnCursorUpdate(info));
159 }
160
OH_InputMethodProxy_SendPrivateCommand(InputMethod_InputMethodProxy * inputMethodProxy,InputMethod_PrivateCommand * privateCommand[],size_t size)161 InputMethod_ErrorCode OH_InputMethodProxy_SendPrivateCommand(
162 InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_PrivateCommand *privateCommand[], size_t size)
163 {
164 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
165 if (errCode != IME_ERR_OK) {
166 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
167 return errCode;
168 }
169 if (privateCommand == nullptr) {
170 IMSA_HILOGE("privateCommand is nullptr");
171 return IME_ERR_NULL_POINTER;
172 }
173
174 if (size > MAX_SYS_PRIVATE_COMMAND_COUNT) {
175 IMSA_HILOGE("privateCommand size is too large: %{public}zu", size);
176 return IME_ERR_PARAMCHECK;
177 }
178
179 std::unordered_map<std::string, PrivateDataValue> command;
180 for (size_t i = 0; i < size; i++) {
181 if (privateCommand[i] == nullptr) {
182 IMSA_HILOGE("privateCommand[%zu] is nullptr", i);
183 return IME_ERR_NULL_POINTER;
184 }
185 command.emplace(privateCommand[i]->key, privateCommand[i]->value);
186 }
187 auto instance = InputMethodController::GetInstance();
188 if (instance == nullptr) {
189 IMSA_HILOGE("InputMethodController is nullptr");
190 return IME_ERR_NULL_POINTER;
191 }
192 return ErrorCodeConvert(instance->SendPrivateCommand(command));
193 }
194
OH_InputMethodProxy_SendMessage(InputMethod_InputMethodProxy * inputMethodProxy,const char16_t * msgId,size_t msgIdLength,const uint8_t * msgParam,size_t msgParamLength)195 InputMethod_ErrorCode OH_InputMethodProxy_SendMessage(InputMethod_InputMethodProxy *inputMethodProxy,
196 const char16_t *msgId, size_t msgIdLength, const uint8_t *msgParam, size_t msgParamLength)
197 {
198 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
199 if (errCode != IME_ERR_OK) {
200 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
201 return errCode;
202 }
203 if (msgId == nullptr || msgParam == nullptr) {
204 IMSA_HILOGE("msgId or msgParam is nullptr");
205 return IME_ERR_NULL_POINTER;
206 }
207 if (msgIdLength > INVALID_MSG_ID_SIZE || msgParamLength > INVALID_MSG_PARAM_SIZE) {
208 IMSA_HILOGE("ArrayBuffer size is invalid, msgIdLength: %{public}zu, msgParamLength: %{public}zu",
209 msgIdLength, msgParamLength);
210 return IME_ERR_PARAMCHECK;
211 }
212 ArrayBuffer arrayBuffer;
213 std::u16string msgIdStr(msgId, msgIdLength);
214 arrayBuffer.msgId = Str16ToStr8(msgIdStr);
215 arrayBuffer.msgParam.assign(msgParam, msgParam + msgParamLength);
216 auto instance = InputMethodController::GetInstance();
217 if (instance == nullptr) {
218 IMSA_HILOGE("InputMethodController is nullptr");
219 return IME_ERR_NULL_POINTER;
220 }
221 return ErrorCodeConvert(instance->SendMessage(arrayBuffer));
222 }
223
OH_InputMethodProxy_RecvMessage(InputMethod_InputMethodProxy * inputMethodProxy,InputMethod_MessageHandlerProxy * messageHandler)224 InputMethod_ErrorCode OH_InputMethodProxy_RecvMessage(
225 InputMethod_InputMethodProxy *inputMethodProxy, InputMethod_MessageHandlerProxy *messageHandler)
226 {
227 auto errCode = IsValidInputMethodProxy(inputMethodProxy);
228 if (errCode != IME_ERR_OK) {
229 IMSA_HILOGE("invalid state, errCode=%{public}d", errCode);
230 return errCode;
231 }
232 if (IsValidMessageHandlerProxy(messageHandler) != IME_ERR_OK) {
233 IMSA_HILOGE("invalid messageHandler");
234 return IME_ERR_NULL_POINTER;
235 }
236 auto instance = InputMethodController::GetInstance();
237 if (instance == nullptr) {
238 IMSA_HILOGE("InputMethodController is nullptr");
239 return IME_ERR_NULL_POINTER;
240 }
241 if (messageHandler == nullptr) {
242 IMSA_HILOGI("UnRegister message handler.");
243 return ErrorCodeConvert(instance->RegisterMsgHandler(nullptr));
244 }
245 IMSA_HILOGI("Register message handler.");
246 std::shared_ptr<MsgHandlerCallbackInterface> msgHandler =
247 std::make_shared<NativeMessageHandlerCallback>(messageHandler);
248 return ErrorCodeConvert(instance->RegisterMsgHandler(msgHandler));
249 }
250 #ifdef __cplusplus
251 }
252 #endif /* __cplusplus */