1 /* 2 * Copyright (C) 2021-2023 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 #ifndef FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H 17 #define FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H 18 19 #include <stdint.h> 20 21 #include <variant> 22 23 #include "global.h" 24 #include "input_attribute.h" 25 #include "panel_info.h" 26 27 namespace OHOS { 28 namespace MiscServices { 29 constexpr uint32_t INVALID_WINDOW_ID = 0; 30 constexpr int32_t INVALID_VALUE = -1; 31 constexpr size_t MAX_PRIVATE_COMMAND_SIZE = 32 * 1024; // 32K 32 constexpr size_t MAX_PRIVATE_COMMAND_COUNT = 5; 33 constexpr size_t MAX_ARRAY_BUFFER_MSG_ID_SIZE = 256; // 256B 34 constexpr size_t MAX_ARRAY_BUFFER_MSG_PARAM_SIZE = 128 * 1024; // 128KB 35 const constexpr char* SYSTEM_CMD_KEY = "sys_cmd"; 36 enum class EnterKeyType { 37 UNSPECIFIED = 0, 38 NONE, 39 GO, 40 SEARCH, 41 SEND, 42 NEXT, 43 DONE, 44 PREVIOUS, 45 NEW_LINE, 46 }; 47 48 enum class TextInputType { 49 NONE = -1, 50 TEXT = 0, 51 MULTILINE, 52 NUMBER, 53 PHONE, 54 DATETIME, 55 EMAIL_ADDRESS, 56 URL, 57 VISIBLE_PASSWORD, 58 NUMBER_PASSWORD, 59 SCREEN_LOCK_PASSWORD, 60 USER_NAME, 61 NEW_PASSWORD, 62 NUMBER_DECIMAL, 63 }; 64 65 enum class Direction { 66 NONE = 0, 67 UP = 1, 68 DOWN, 69 LEFT, 70 RIGHT, 71 }; 72 73 enum class SecurityMode : int32_t { 74 BASIC = 0, 75 FULL = 1, 76 }; 77 78 enum class ExtendAction { 79 SELECT_ALL = 0, 80 CUT = 3, 81 COPY, 82 PASTE, 83 }; 84 85 class Configuration { 86 public: GetEnterKeyType()87 EnterKeyType GetEnterKeyType() const 88 { 89 return enterKeyType; 90 } 91 SetEnterKeyType(EnterKeyType keyType)92 void SetEnterKeyType(EnterKeyType keyType) 93 { 94 enterKeyType = keyType; 95 } 96 GetTextInputType()97 TextInputType GetTextInputType() const 98 { 99 return textInputType; 100 } 101 SetTextInputType(TextInputType textType)102 void SetTextInputType(TextInputType textType) 103 { 104 textInputType = textType; 105 } 106 107 private: 108 EnterKeyType enterKeyType = EnterKeyType::UNSPECIFIED; 109 TextInputType textInputType = TextInputType::TEXT; 110 }; 111 112 struct CursorInfo { 113 double left = -1.0; 114 double top = -1.0; 115 double width = -1.0; 116 double height = -1.0; 117 bool operator==(const CursorInfo &info) const 118 { 119 return (left == info.left && top == info.top && width == info.width && height == info.height); 120 } 121 }; 122 123 class KeyEvent {}; 124 125 enum class KeyboardStatus : int32_t { NONE = 0, HIDE, SHOW }; // soft keyboard 126 127 enum Trigger : int32_t { IME_APP, IMF, END }; 128 struct PanelStatusInfo { 129 PanelInfo panelInfo; 130 bool visible{ false }; 131 Trigger trigger{ END }; 132 bool operator==(const PanelStatusInfo &info) const 133 { 134 return info.panelInfo.panelFlag == panelInfo.panelFlag && info.panelInfo.panelType == panelInfo.panelType 135 && info.visible == visible && info.trigger == trigger; 136 } 137 }; 138 139 class FunctionKey { 140 public: GetEnterKeyType()141 EnterKeyType GetEnterKeyType() const 142 { 143 return enterKeyType; 144 } 145 SetEnterKeyType(EnterKeyType keyType)146 void SetEnterKeyType(EnterKeyType keyType) 147 { 148 enterKeyType = keyType; 149 } 150 151 private: 152 EnterKeyType enterKeyType = EnterKeyType::UNSPECIFIED; 153 }; 154 155 struct ArrayBuffer { 156 size_t jsArgc = 0; 157 std::string msgId; 158 std::vector<uint8_t> msgParam; IsSizeValidArrayBuffer159 static bool IsSizeValid(const ArrayBuffer &arrayBuffer) 160 { 161 if (arrayBuffer.msgId.size() > MAX_ARRAY_BUFFER_MSG_ID_SIZE) { 162 IMSA_HILOGE("Invalid msgId size: %{public}zu.", arrayBuffer.msgId.size()); 163 return false; 164 } 165 if (arrayBuffer.msgParam.size() > MAX_ARRAY_BUFFER_MSG_PARAM_SIZE) { 166 IMSA_HILOGE("Invalid msgParam size: %{public}zu.", arrayBuffer.msgParam.size()); 167 return false; 168 } 169 return true; 170 } 171 bool operator==(const ArrayBuffer &arrayBuffer) const 172 { 173 return jsArgc == arrayBuffer.jsArgc && msgId == arrayBuffer.msgId && msgParam == arrayBuffer.msgParam; 174 } 175 }; 176 177 struct Range { 178 int32_t start = INVALID_VALUE; 179 int32_t end = INVALID_VALUE; 180 bool operator==(const Range &range) const 181 { 182 return start == range.start && end == range.end; 183 } 184 }; 185 186 struct TextSelection { 187 int32_t oldBegin = INVALID_VALUE; 188 int32_t oldEnd = INVALID_VALUE; 189 int32_t newBegin = INVALID_VALUE; 190 int32_t newEnd = INVALID_VALUE; 191 }; 192 193 enum PrivateDataValueType : int32_t { VALUE_TYPE_STRING = 0, VALUE_TYPE_BOOL, VALUE_TYPE_NUMBER }; 194 using PrivateDataValue = std::variant<std::string, bool, int32_t>; 195 196 struct TextTotalConfig { 197 public: 198 InputAttribute inputAttribute = {}; 199 CursorInfo cursorInfo = {}; 200 TextSelection textSelection = {}; 201 uint32_t windowId = INVALID_WINDOW_ID; 202 double positionY = 0; 203 double height = 0; 204 std::unordered_map<std::string, PrivateDataValue> privateCommand = {}; 205 ToStringTextTotalConfig206 std::string ToString() const 207 { 208 std::string config; 209 config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" 210 + std::to_string(inputAttribute.enterKeyType) + "/" 211 + std::to_string(inputAttribute.isTextPreviewSupported)); 212 config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" 213 + std::to_string(height)); 214 config.append( 215 " oldRange: " + std::to_string(textSelection.oldBegin) + "/" + std::to_string(textSelection.oldEnd)); 216 config.append( 217 " newRange: " + std::to_string(textSelection.newBegin) + "/" + std::to_string(textSelection.newEnd)); 218 config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" 219 + std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height)); 220 return config; 221 } 222 }; 223 struct TextConfig { 224 InputAttribute inputAttribute = {}; 225 CursorInfo cursorInfo = {}; 226 Range range = {}; 227 uint32_t windowId = INVALID_WINDOW_ID; 228 double positionY = 0; 229 double height = 0; 230 std::unordered_map<std::string, PrivateDataValue> privateCommand = {}; 231 ToStringTextConfig232 std::string ToString() const 233 { 234 std::string config; 235 config.append("pattern/enterKey/preview: " + std::to_string(inputAttribute.inputPattern) + "/" 236 + std::to_string(inputAttribute.enterKeyType) + "/" 237 + std::to_string(inputAttribute.isTextPreviewSupported)); 238 config.append(" windowId/y/height: " + std::to_string(windowId) + "/" + std::to_string(positionY) + "/" 239 + std::to_string(height)); 240 config.append(" range: " + std::to_string(range.start) + "/" + std::to_string(range.end)); 241 config.append(" cursor: " + std::to_string(cursorInfo.left) + "/" + std::to_string(cursorInfo.top) + "/" 242 + std::to_string(cursorInfo.width) + "/" + std::to_string(cursorInfo.height)); 243 return config; 244 } 245 IsPrivateCommandValidTextConfig246 static bool IsPrivateCommandValid(const std::unordered_map<std::string, PrivateDataValue> &privateCommand) 247 { 248 size_t privateCommandSize = privateCommand.size(); 249 size_t maxSize = IsSystemPrivateCommand(privateCommand) ? (MAX_PRIVATE_COMMAND_COUNT + 1) 250 : MAX_PRIVATE_COMMAND_COUNT; 251 if (privateCommandSize == 0 || privateCommandSize > maxSize) { 252 IMSA_HILOGE("privateCommand size must more than 0 and less than 5."); 253 return false; 254 } 255 size_t totalSize = 0; 256 for (const auto &iter : privateCommand) { 257 size_t keySize = iter.first.size(); 258 size_t idx = iter.second.index(); 259 size_t valueSize = 0; 260 261 if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_STRING)) { 262 auto stringValue = std::get_if<std::string>(&iter.second); 263 if (stringValue == nullptr) { 264 IMSA_HILOGE("get stringValue failed."); 265 return false; 266 } 267 valueSize = (*stringValue).size(); 268 } else if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_BOOL)) { 269 valueSize = sizeof(bool); 270 } else if (idx == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_NUMBER)) { 271 valueSize = sizeof(int32_t); 272 } 273 totalSize = totalSize + keySize + valueSize; 274 } 275 if (totalSize > MAX_PRIVATE_COMMAND_SIZE) { 276 IMSA_HILOGE("totalSize : %{public}zu", totalSize); 277 return false; 278 } 279 return true; 280 } IsSystemPrivateCommandTextConfig281 static bool IsSystemPrivateCommand(const std::unordered_map<std::string, PrivateDataValue> &privateCommand) 282 { 283 IMSA_HILOGD("in."); 284 size_t privateCommandSize = privateCommand.size(); 285 if (privateCommandSize == 0 || privateCommandSize > MAX_PRIVATE_COMMAND_COUNT) { 286 IMSA_HILOGE("privateCommand size must more than 0 and less than 5."); 287 return false; 288 } 289 auto it = privateCommand.find(SYSTEM_CMD_KEY); 290 if (it != privateCommand.end()) { 291 // if privateCommand has the key system_cmd and value is 1, it's a system privateCommand. 292 if (it->second.index() == static_cast<size_t>(PrivateDataValueType::VALUE_TYPE_NUMBER)) { 293 auto numberValue = std::get_if<int32_t>(&it->second); 294 if (numberValue == nullptr) { 295 IMSA_HILOGE("get stringValue failed."); 296 return false; 297 } 298 return *numberValue == 1; 299 } 300 } 301 return false; 302 } 303 }; 304 305 enum class InputType : int32_t { NONE = -1, CAMERA_INPUT = 0, SECURITY_INPUT, VOICE_INPUT, END }; 306 307 enum class SwitchTrigger : uint32_t { CURRENT_IME = 0, SYSTEM_APP, IMSA, NATIVE_SA}; 308 309 enum class RequestKeyboardReason : int32_t { 310 NONE = 0, // no event reason 311 MOUSE = 1, // user triggered mouse event 312 TOUCH = 2, // user triggered touch event 313 OTHER = 20 // other reason 314 }; 315 316 struct AttachOptions { 317 bool isShowKeyboard = false; 318 RequestKeyboardReason requestKeyboardReason { RequestKeyboardReason::NONE }; 319 }; 320 321 } // namespace MiscServices 322 } // namespace OHOS 323 #endif // FRAMEWORKS_INPUTMETHOD_CONTROLLER_INCLUDE_INPUT_METHOD_UTILS_H 324