1 /* 2 * Copyright (c) 2022-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 #ifndef INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H 16 #define INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H 17 18 #include <unordered_map> 19 #include <mutex> 20 21 #include "edit_async_call.h" 22 #include "block_queue.h" 23 #include "calling_window_info.h" 24 #include "global.h" 25 #include "js_callback_object.h" 26 #include "js_message_handler_info.h" 27 #include "js_util.h" 28 #include "msg_handler_callback_interface.h" 29 #include "native_engine/native_engine.h" 30 #include "native_engine/native_value.h" 31 #include "wm_common.h" 32 #include "text_input_client_listener.h" 33 #include "input_method_utils.h" 34 35 namespace OHOS { 36 namespace MiscServices { 37 struct PrivateCommandInfo { 38 std::chrono::system_clock::time_point timestamp{}; 39 std::unordered_map<std::string, PrivateDataValue> privateCommand; 40 bool operator==(const PrivateCommandInfo &info) const 41 { 42 return (timestamp == info.timestamp && privateCommand == info.privateCommand); 43 } 44 }; 45 46 struct JsRect { 47 static napi_value Write(napi_env env, const Rosen::Rect &nativeObject); 48 static bool Read(napi_env env, napi_value jsObject, Rosen::Rect &nativeObject); 49 }; 50 51 struct JsCallingWindowInfo { 52 static napi_value Write(napi_env env, const CallingWindowInfo &nativeObject); 53 static bool Read(napi_env env, napi_value object, CallingWindowInfo &nativeObject); 54 }; 55 56 struct JsRange { 57 static napi_value Write(napi_env env, const Range &nativeObject); 58 static bool Read(napi_env env, napi_value jsObject, Range &nativeObject); 59 }; 60 61 struct JsInputAttribute { 62 static napi_value Write(napi_env env, const InputAttribute &nativeObject); 63 static bool Read(napi_env env, napi_value jsObject, InputAttribute &nativeObject); 64 }; 65 66 struct JsAttachOptions { 67 static napi_value Write(napi_env env, const AttachOptions &attachOptions); 68 static bool Read(napi_env env, napi_value jsObject, AttachOptions &attachOptions); 69 }; 70 71 struct SendKeyFunctionContext : public AsyncCall::Context { 72 bool isSendKeyFunction = false; 73 int32_t action = 0; 74 napi_status status = napi_generic_failure; SendKeyFunctionContextSendKeyFunctionContext75 SendKeyFunctionContext() : Context(nullptr, nullptr){}; SendKeyFunctionContextSendKeyFunctionContext76 SendKeyFunctionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 77 operatorSendKeyFunctionContext78 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 79 { 80 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 81 return Context::operator()(env, argc, argv, self); 82 } 83 operatorSendKeyFunctionContext84 napi_status operator()(napi_env env, napi_value *result) override 85 { 86 if (status != napi_ok) { 87 output_ = nullptr; 88 return status; 89 } 90 return Context::operator()(env, result); 91 } 92 }; 93 94 struct MoveCursorContext : public AsyncCall::Context { 95 int32_t num = 0; 96 napi_status status = napi_generic_failure; MoveCursorContextMoveCursorContext97 MoveCursorContext() : Context(nullptr, nullptr){}; MoveCursorContextMoveCursorContext98 MoveCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 99 operatorMoveCursorContext100 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 101 { 102 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 103 return Context::operator()(env, argc, argv, self); 104 } operatorMoveCursorContext105 napi_status operator()(napi_env env, napi_value *result) override 106 { 107 if (status != napi_ok) { 108 output_ = nullptr; 109 return status; 110 } 111 return Context::operator()(env, result); 112 } 113 }; 114 115 struct DeleteForwardContext : public AsyncCall::Context { 116 bool isDeleteForward = false; 117 int32_t length = 0; 118 napi_status status = napi_generic_failure; DeleteForwardContextDeleteForwardContext119 DeleteForwardContext() : Context(nullptr, nullptr){}; DeleteForwardContextDeleteForwardContext120 DeleteForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 121 operatorDeleteForwardContext122 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 123 { 124 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 125 return Context::operator()(env, argc, argv, self); 126 } operatorDeleteForwardContext127 napi_status operator()(napi_env env, napi_value *result) override 128 { 129 if (status != napi_ok) { 130 output_ = nullptr; 131 return status; 132 } 133 return Context::operator()(env, result); 134 } 135 }; 136 137 struct DeleteBackwardContext : public AsyncCall::Context { 138 bool isDeleteBackward = false; 139 int32_t length = 0; 140 napi_status status = napi_generic_failure; DeleteBackwardContextDeleteBackwardContext141 DeleteBackwardContext() : Context(nullptr, nullptr){}; DeleteBackwardContextDeleteBackwardContext142 DeleteBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 143 operatorDeleteBackwardContext144 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 145 { 146 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 147 return Context::operator()(env, argc, argv, self); 148 } operatorDeleteBackwardContext149 napi_status operator()(napi_env env, napi_value *result) override 150 { 151 if (status != napi_ok) { 152 output_ = nullptr; 153 return status; 154 } 155 return Context::operator()(env, result); 156 } 157 }; 158 159 struct InsertTextContext : public AsyncCall::Context { 160 bool isInsertText = false; 161 std::string text; 162 napi_status status = napi_generic_failure; InsertTextContextInsertTextContext163 InsertTextContext() : Context(nullptr, nullptr){}; InsertTextContextInsertTextContext164 InsertTextContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 165 operatorInsertTextContext166 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 167 { 168 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 169 return Context::operator()(env, argc, argv, self); 170 } operatorInsertTextContext171 napi_status operator()(napi_env env, napi_value *result) override 172 { 173 if (status != napi_ok) { 174 output_ = nullptr; 175 return status; 176 } 177 return Context::operator()(env, result); 178 } 179 }; 180 181 struct GetForwardContext : public AsyncCall::Context { 182 int32_t length = 0; 183 std::string text; 184 napi_status status = napi_generic_failure; GetForwardContextGetForwardContext185 GetForwardContext() : Context(nullptr, nullptr){}; GetForwardContextGetForwardContext186 GetForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 187 operatorGetForwardContext188 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 189 { 190 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 191 return Context::operator()(env, argc, argv, self); 192 } operatorGetForwardContext193 napi_status operator()(napi_env env, napi_value *result) override 194 { 195 if (status != napi_ok) { 196 output_ = nullptr; 197 return status; 198 } 199 return Context::operator()(env, result); 200 } 201 }; 202 203 struct GetBackwardContext : public AsyncCall::Context { 204 int32_t length = 0; 205 std::string text; 206 napi_status status = napi_generic_failure; GetBackwardContextGetBackwardContext207 GetBackwardContext() : Context(nullptr, nullptr){}; GetBackwardContextGetBackwardContext208 GetBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 209 operatorGetBackwardContext210 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 211 { 212 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 213 return Context::operator()(env, argc, argv, self); 214 } operatorGetBackwardContext215 napi_status operator()(napi_env env, napi_value *result) override 216 { 217 if (status != napi_ok) { 218 output_ = nullptr; 219 return status; 220 } 221 return Context::operator()(env, result); 222 } 223 }; 224 225 struct GetEditorAttributeContext : public AsyncCall::Context { 226 InputAttribute inputAttribute; GetEditorAttributeContextGetEditorAttributeContext227 GetEditorAttributeContext() : Context(nullptr, nullptr){}; GetEditorAttributeContextGetEditorAttributeContext228 GetEditorAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; operatorGetEditorAttributeContext229 napi_status operator()(napi_env env, napi_value *result) override 230 { 231 if (status_ != napi_ok) { 232 output_ = nullptr; 233 return status_; 234 } 235 return Context::operator()(env, result); 236 } 237 }; 238 239 struct SelectContext : public AsyncCall::Context { 240 int32_t start = 0; 241 int32_t end = 0; 242 int32_t direction = 0; 243 napi_status status = napi_generic_failure; SelectContextSelectContext244 SelectContext() : Context(nullptr, nullptr){}; SelectContextSelectContext245 SelectContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; operatorSelectContext246 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 247 { 248 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 249 return Context::operator()(env, argc, argv, self); 250 } operatorSelectContext251 napi_status operator()(napi_env env, napi_value *result) override 252 { 253 if (status != napi_ok) { 254 output_ = nullptr; 255 return status; 256 } 257 return Context::operator()(env, result); 258 } 259 }; 260 261 struct GetTextIndexAtCursorContext : public AsyncCall::Context { 262 int32_t index = 0; 263 napi_status status = napi_generic_failure; GetTextIndexAtCursorContextGetTextIndexAtCursorContext264 GetTextIndexAtCursorContext() : Context(nullptr, nullptr){}; GetTextIndexAtCursorContextGetTextIndexAtCursorContext265 GetTextIndexAtCursorContext(InputAction input, OutputAction output) 266 : Context(std::move(input), std::move(output)){}; 267 operatorGetTextIndexAtCursorContext268 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 269 { 270 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 271 return Context::operator()(env, argc, argv, self); 272 } operatorGetTextIndexAtCursorContext273 napi_status operator()(napi_env env, napi_value *result) override 274 { 275 if (status != napi_ok) { 276 output_ = nullptr; 277 return status; 278 } 279 return Context::operator()(env, result); 280 } 281 }; 282 283 struct SendExtendActionContext : public AsyncCall::Context { 284 int32_t action = 0; SendExtendActionContextSendExtendActionContext285 SendExtendActionContext() : Context(nullptr, nullptr){}; SendExtendActionContextSendExtendActionContext286 SendExtendActionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){}; 287 operatorSendExtendActionContext288 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 289 { 290 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 291 return Context::operator()(env, argc, argv, self); 292 } operatorSendExtendActionContext293 napi_status operator()(napi_env env, napi_value *result) override 294 { 295 if (status_ != napi_ok) { 296 output_ = nullptr; 297 return status_; 298 } 299 return Context::operator()(env, result); 300 } 301 }; 302 303 struct SendPrivateCommandContext : public AsyncCall::Context { 304 std::unordered_map<std::string, PrivateDataValue> privateCommand; 305 PrivateCommandInfo info; 306 napi_status status = napi_generic_failure; SendPrivateCommandContextSendPrivateCommandContext307 SendPrivateCommandContext() : Context(nullptr, nullptr){}; 308 operatorSendPrivateCommandContext309 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 310 { 311 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 312 return Context::operator()(env, argc, argv, self); 313 } 314 operatorSendPrivateCommandContext315 napi_status operator()(napi_env env, napi_value *result) override 316 { 317 if (status != napi_ok) { 318 output_ = nullptr; 319 return status; 320 } 321 return Context::operator()(env, result); 322 } 323 }; 324 325 struct GetCallingWindowInfoContext : public AsyncCall::Context { 326 CallingWindowInfo windowInfo{}; GetCallingWindowInfoContextGetCallingWindowInfoContext327 GetCallingWindowInfoContext() : Context(nullptr, nullptr){}; operatorGetCallingWindowInfoContext328 napi_status operator()(napi_env env, napi_value *result) override 329 { 330 if (status_ != napi_ok) { 331 output_ = nullptr; 332 return status_; 333 } 334 return Context::operator()(env, result); 335 } 336 }; 337 338 struct SetPreviewTextContext : public AsyncCall::Context { 339 std::string text; 340 Range range; SetPreviewTextContextSetPreviewTextContext341 SetPreviewTextContext() : Context(nullptr, nullptr){}; operatorSetPreviewTextContext342 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 343 { 344 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 345 return Context::operator()(env, argc, argv, self); 346 } operatorSetPreviewTextContext347 napi_status operator()(napi_env env, napi_value *result) override 348 { 349 if (status_ != napi_ok) { 350 output_ = nullptr; 351 return status_; 352 } 353 return Context::operator()(env, result); 354 } 355 }; 356 357 struct FinishTextPreviewContext : public AsyncCall::Context { FinishTextPreviewContextFinishTextPreviewContext358 FinishTextPreviewContext() : Context(nullptr, nullptr){}; operatorFinishTextPreviewContext359 napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override 360 { 361 CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg); 362 return Context::operator()(env, argc, argv, self); 363 } operatorFinishTextPreviewContext364 napi_status operator()(napi_env env, napi_value *result) override 365 { 366 if (status_ != napi_ok) { 367 output_ = nullptr; 368 return status_; 369 } 370 return Context::operator()(env, result); 371 } 372 }; 373 374 class JsTextInputClientEngine : public TextInputClientListener { 375 public: 376 JsTextInputClientEngine() = default; 377 ~JsTextInputClientEngine() = default; 378 static napi_value Init(napi_env env, napi_value info); 379 static napi_value SendKeyFunction(napi_env env, napi_callback_info info); 380 static napi_value DeleteForward(napi_env env, napi_callback_info info); 381 static napi_value DeleteBackward(napi_env env, napi_callback_info info); 382 static napi_value InsertText(napi_env env, napi_callback_info info); 383 static napi_value GetForward(napi_env env, napi_callback_info info); 384 static napi_value GetBackward(napi_env env, napi_callback_info info); 385 static napi_value MoveCursor(napi_env env, napi_callback_info info); 386 static napi_value GetEditorAttribute(napi_env env, napi_callback_info info); 387 static napi_value GetTextIndexAtCursor(napi_env env, napi_callback_info info); 388 static napi_value GetTextInputClientInstance(napi_env env); 389 static napi_value SelectByRange(napi_env env, napi_callback_info info); 390 static napi_value SelectByMovement(napi_env env, napi_callback_info info); 391 static napi_value SendExtendAction(napi_env env, napi_callback_info info); 392 static napi_value InsertTextSync(napi_env env, napi_callback_info info); 393 static napi_value MoveCursorSync(napi_env env, napi_callback_info info); 394 static napi_value GetEditorAttributeSync(napi_env env, napi_callback_info info); 395 static napi_value SelectByRangeSync(napi_env env, napi_callback_info info); 396 static napi_value SelectByMovementSync(napi_env env, napi_callback_info info); 397 static napi_value GetTextIndexAtCursorSync(napi_env env, napi_callback_info info); 398 static napi_value DeleteForwardSync(napi_env env, napi_callback_info info); 399 static napi_value DeleteBackwardSync(napi_env env, napi_callback_info info); 400 static napi_value GetForwardSync(napi_env env, napi_callback_info info); 401 static napi_value GetBackwardSync(napi_env env, napi_callback_info info); 402 static napi_value GetCallingWindowInfo(napi_env env, napi_callback_info info); 403 static napi_value SendPrivateCommand(napi_env env, napi_callback_info info); 404 static napi_value SetPreviewText(napi_env env, napi_callback_info info); 405 static napi_value SetPreviewTextSync(napi_env env, napi_callback_info info); 406 static napi_value FinishTextPreview(napi_env env, napi_callback_info info); 407 static napi_value FinishTextPreviewSync(napi_env env, napi_callback_info info); 408 static napi_value SendMessage(napi_env env, napi_callback_info info); 409 static napi_value RecvMessage(napi_env env, napi_callback_info info); 410 static napi_value GetAttachOptions(napi_env env, napi_callback_info info); 411 static napi_value Subscribe(napi_env env, napi_callback_info info); 412 static napi_value UnSubscribe(napi_env env, napi_callback_info info); 413 void OnAttachOptionsChanged(const AttachOptions &attachOptions) override; 414 class JsMessageHandler : public MsgHandlerCallbackInterface { 415 public: JsMessageHandler(napi_env env,napi_value onTerminated,napi_value onMessage)416 explicit JsMessageHandler(napi_env env, napi_value onTerminated, napi_value onMessage) 417 : jsMessageHandler_(std::make_shared<JSMsgHandlerCallbackObject>(env, onTerminated, onMessage)) {}; ~JsMessageHandler()418 virtual ~JsMessageHandler() {}; 419 int32_t OnTerminated() override; 420 int32_t OnMessage(const ArrayBuffer &arrayBuffer) override; 421 422 private: 423 std::mutex callbackObjectMutex_; 424 std::shared_ptr<JSMsgHandlerCallbackObject> jsMessageHandler_ = nullptr; 425 }; 426 private: 427 static napi_status GetSelectRange(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt); 428 static napi_status GetSelectMovement(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt); 429 430 static napi_value JsConstructor(napi_env env, napi_callback_info info); 431 static std::shared_ptr<JsTextInputClientEngine> GetTextInputClientEngine(); 432 static bool InitTextInputClientEngine(); 433 static napi_value GetResult(napi_env env, std::string &text); 434 static napi_value GetResultEditorAttribute(napi_env env, 435 std::shared_ptr<GetEditorAttributeContext> getEditorAttribute); 436 static napi_value HandleParamCheckFailure(napi_env env); 437 static napi_status GetPreviewTextParam(napi_env env, size_t argc, napi_value *argv, std::string &text, 438 Range &range); 439 static bool IsTargetDeviceType(int32_t resDeviceType); 440 void RegisterListener(napi_value callback, std::string type, std::shared_ptr<JSCallbackObject> callbackObj); 441 void UnRegisterListener(napi_value callback, std::string type); 442 443 struct UvEntry { 444 std::vector<std::shared_ptr<JSCallbackObject>> vecCopy; 445 std::string type; 446 AttachOptions attachOptions; UvEntryUvEntry447 explicit UvEntry(const std::vector<std::shared_ptr<JSCallbackObject>> &cbVec, const std::string &type) 448 : vecCopy(cbVec), type(type) 449 { 450 } 451 }; 452 using EntrySetter = std::function<void(UvEntry &)>; 453 static std::shared_ptr<AppExecFwk::EventHandler> GetEventHandler(); 454 std::shared_ptr<UvEntry> GetEntry(const std::string &type, EntrySetter entrySetter = nullptr); 455 std::recursive_mutex mutex_; 456 std::map<std::string, std::vector<std::shared_ptr<JSCallbackObject>>> jsCbMap_; 457 458 static const std::string TIC_CLASS_NAME; 459 static thread_local napi_ref TICRef_; 460 static std::shared_ptr<AsyncCall::TaskQueue> taskQueue_; 461 static BlockQueue<PrivateCommandInfo> privateCommandQueue_; GenerateTraceId()462 static std::string GenerateTraceId() 463 { 464 auto traceId = traceId_++; 465 return std::to_string(traceId); 466 } 467 static uint32_t traceId_; 468 469 static BlockQueue<MessageHandlerInfo> messageHandlerQueue_; 470 static std::mutex engineMutex_; 471 static std::shared_ptr<JsTextInputClientEngine> textInputClientEngine_; 472 static std::mutex eventHandlerMutex_; 473 static std::shared_ptr<AppExecFwk::EventHandler> handler_; 474 static int32_t deviceTypeCache_; 475 }; 476 } // namespace MiscServices 477 } // namespace OHOS 478 #endif // INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H