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 
20 #include "async_call.h"
21 #include "block_queue.h"
22 #include "calling_window_info.h"
23 #include "global.h"
24 #include "js_util.h"
25 #include "native_engine/native_engine.h"
26 #include "native_engine/native_value.h"
27 #include "wm_common.h"
28 
29 namespace OHOS {
30 namespace MiscServices {
31 struct PrivateCommandInfo {
32     std::chrono::system_clock::time_point timestamp{};
33     std::unordered_map<std::string, PrivateDataValue> privateCommand;
34     bool operator==(const PrivateCommandInfo &info) const
35     {
36         return (timestamp == info.timestamp && privateCommand == info.privateCommand);
37     }
38 };
39 
40 struct JsRect {
41     static napi_value Write(napi_env env, const Rosen::Rect &nativeObject);
42     static bool Read(napi_env env, napi_value jsObject, Rosen::Rect &nativeObject);
43 };
44 
45 struct JsCallingWindowInfo {
46     static napi_value Write(napi_env env, const CallingWindowInfo &nativeObject);
47     static bool Read(napi_env env, napi_value object, CallingWindowInfo &nativeObject);
48 };
49 
50 struct JsRange {
51     static napi_value Write(napi_env env, const Range &nativeObject);
52     static bool Read(napi_env env, napi_value jsObject, Range &nativeObject);
53 };
54 
55 struct JsInputAttribute {
56     static napi_value Write(napi_env env, const InputAttribute &nativeObject);
57     static bool Read(napi_env env, napi_value jsObject, InputAttribute &nativeObject);
58 };
59 
60 struct SendKeyFunctionContext : public AsyncCall::Context {
61     bool isSendKeyFunction = false;
62     int32_t action = 0;
63     napi_status status = napi_generic_failure;
SendKeyFunctionContextSendKeyFunctionContext64     SendKeyFunctionContext() : Context(nullptr, nullptr){};
SendKeyFunctionContextSendKeyFunctionContext65     SendKeyFunctionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
66 
operatorSendKeyFunctionContext67     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
68     {
69         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
70         return Context::operator()(env, argc, argv, self);
71     }
72 
operatorSendKeyFunctionContext73     napi_status operator()(napi_env env, napi_value *result) override
74     {
75         if (status != napi_ok) {
76             output_ = nullptr;
77             return status;
78         }
79         return Context::operator()(env, result);
80     }
81 };
82 
83 struct MoveCursorContext : public AsyncCall::Context {
84     int32_t num = 0;
85     napi_status status = napi_generic_failure;
MoveCursorContextMoveCursorContext86     MoveCursorContext() : Context(nullptr, nullptr){};
MoveCursorContextMoveCursorContext87     MoveCursorContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
88 
operatorMoveCursorContext89     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
90     {
91         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
92         return Context::operator()(env, argc, argv, self);
93     }
operatorMoveCursorContext94     napi_status operator()(napi_env env, napi_value *result) override
95     {
96         if (status != napi_ok) {
97             output_ = nullptr;
98             return status;
99         }
100         return Context::operator()(env, result);
101     }
102 };
103 
104 struct DeleteForwardContext : public AsyncCall::Context {
105     bool isDeleteForward = false;
106     int32_t length = 0;
107     napi_status status = napi_generic_failure;
DeleteForwardContextDeleteForwardContext108     DeleteForwardContext() : Context(nullptr, nullptr){};
DeleteForwardContextDeleteForwardContext109     DeleteForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
110 
operatorDeleteForwardContext111     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
112     {
113         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
114         return Context::operator()(env, argc, argv, self);
115     }
operatorDeleteForwardContext116     napi_status operator()(napi_env env, napi_value *result) override
117     {
118         if (status != napi_ok) {
119             output_ = nullptr;
120             return status;
121         }
122         return Context::operator()(env, result);
123     }
124 };
125 
126 struct DeleteBackwardContext : public AsyncCall::Context {
127     bool isDeleteBackward = false;
128     int32_t length = 0;
129     napi_status status = napi_generic_failure;
DeleteBackwardContextDeleteBackwardContext130     DeleteBackwardContext() : Context(nullptr, nullptr){};
DeleteBackwardContextDeleteBackwardContext131     DeleteBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
132 
operatorDeleteBackwardContext133     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
134     {
135         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
136         return Context::operator()(env, argc, argv, self);
137     }
operatorDeleteBackwardContext138     napi_status operator()(napi_env env, napi_value *result) override
139     {
140         if (status != napi_ok) {
141             output_ = nullptr;
142             return status;
143         }
144         return Context::operator()(env, result);
145     }
146 };
147 
148 struct InsertTextContext : public AsyncCall::Context {
149     bool isInsertText = false;
150     std::string text;
151     napi_status status = napi_generic_failure;
InsertTextContextInsertTextContext152     InsertTextContext() : Context(nullptr, nullptr){};
InsertTextContextInsertTextContext153     InsertTextContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
154 
operatorInsertTextContext155     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
156     {
157         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
158         return Context::operator()(env, argc, argv, self);
159     }
operatorInsertTextContext160     napi_status operator()(napi_env env, napi_value *result) override
161     {
162         if (status != napi_ok) {
163             output_ = nullptr;
164             return status;
165         }
166         return Context::operator()(env, result);
167     }
168 };
169 
170 struct GetForwardContext : public AsyncCall::Context {
171     int32_t length = 0;
172     std::string text;
173     napi_status status = napi_generic_failure;
GetForwardContextGetForwardContext174     GetForwardContext() : Context(nullptr, nullptr){};
GetForwardContextGetForwardContext175     GetForwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
176 
operatorGetForwardContext177     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
178     {
179         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
180         return Context::operator()(env, argc, argv, self);
181     }
operatorGetForwardContext182     napi_status operator()(napi_env env, napi_value *result) override
183     {
184         if (status != napi_ok) {
185             output_ = nullptr;
186             return status;
187         }
188         return Context::operator()(env, result);
189     }
190 };
191 
192 struct GetBackwardContext : public AsyncCall::Context {
193     int32_t length = 0;
194     std::string text;
195     napi_status status = napi_generic_failure;
GetBackwardContextGetBackwardContext196     GetBackwardContext() : Context(nullptr, nullptr){};
GetBackwardContextGetBackwardContext197     GetBackwardContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
198 
operatorGetBackwardContext199     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
200     {
201         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
202         return Context::operator()(env, argc, argv, self);
203     }
operatorGetBackwardContext204     napi_status operator()(napi_env env, napi_value *result) override
205     {
206         if (status != napi_ok) {
207             output_ = nullptr;
208             return status;
209         }
210         return Context::operator()(env, result);
211     }
212 };
213 
214 struct GetEditorAttributeContext : public AsyncCall::Context {
215     InputAttribute inputAttribute;
GetEditorAttributeContextGetEditorAttributeContext216     GetEditorAttributeContext() : Context(nullptr, nullptr){};
GetEditorAttributeContextGetEditorAttributeContext217     GetEditorAttributeContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
operatorGetEditorAttributeContext218     napi_status operator()(napi_env env, napi_value *result) override
219     {
220         if (status_ != napi_ok) {
221             output_ = nullptr;
222             return status_;
223         }
224         return Context::operator()(env, result);
225     }
226 };
227 
228 struct SelectContext : public AsyncCall::Context {
229     int32_t start = 0;
230     int32_t end = 0;
231     int32_t direction = 0;
232     napi_status status = napi_generic_failure;
SelectContextSelectContext233     SelectContext() : Context(nullptr, nullptr){};
SelectContextSelectContext234     SelectContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
operatorSelectContext235     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
236     {
237         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
238         return Context::operator()(env, argc, argv, self);
239     }
operatorSelectContext240     napi_status operator()(napi_env env, napi_value *result) override
241     {
242         if (status != napi_ok) {
243             output_ = nullptr;
244             return status;
245         }
246         return Context::operator()(env, result);
247     }
248 };
249 
250 struct GetTextIndexAtCursorContext : public AsyncCall::Context {
251     int32_t index = 0;
252     napi_status status = napi_generic_failure;
GetTextIndexAtCursorContextGetTextIndexAtCursorContext253     GetTextIndexAtCursorContext() : Context(nullptr, nullptr){};
GetTextIndexAtCursorContextGetTextIndexAtCursorContext254     GetTextIndexAtCursorContext(InputAction input, OutputAction output)
255         : Context(std::move(input), std::move(output)){};
256 
operatorGetTextIndexAtCursorContext257     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
258     {
259         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
260         return Context::operator()(env, argc, argv, self);
261     }
operatorGetTextIndexAtCursorContext262     napi_status operator()(napi_env env, napi_value *result) override
263     {
264         if (status != napi_ok) {
265             output_ = nullptr;
266             return status;
267         }
268         return Context::operator()(env, result);
269     }
270 };
271 
272 struct SendExtendActionContext : public AsyncCall::Context {
273     int32_t action = 0;
SendExtendActionContextSendExtendActionContext274     SendExtendActionContext() : Context(nullptr, nullptr){};
SendExtendActionContextSendExtendActionContext275     SendExtendActionContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
276 
operatorSendExtendActionContext277     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
278     {
279         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
280         return Context::operator()(env, argc, argv, self);
281     }
operatorSendExtendActionContext282     napi_status operator()(napi_env env, napi_value *result) override
283     {
284         if (status_ != napi_ok) {
285             output_ = nullptr;
286             return status_;
287         }
288         return Context::operator()(env, result);
289     }
290 };
291 
292 struct SendPrivateCommandContext : public AsyncCall::Context {
293     std::unordered_map<std::string, PrivateDataValue> privateCommand;
294     PrivateCommandInfo info;
295     napi_status status = napi_generic_failure;
SendPrivateCommandContextSendPrivateCommandContext296     SendPrivateCommandContext() : Context(nullptr, nullptr){};
297 
operatorSendPrivateCommandContext298     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
299     {
300         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
301         return Context::operator()(env, argc, argv, self);
302     }
303 
operatorSendPrivateCommandContext304     napi_status operator()(napi_env env, napi_value *result) override
305     {
306         if (status != napi_ok) {
307             output_ = nullptr;
308             return status;
309         }
310         return Context::operator()(env, result);
311     }
312 };
313 
314 struct GetCallingWindowInfoContext : public AsyncCall::Context {
315     CallingWindowInfo windowInfo{};
GetCallingWindowInfoContextGetCallingWindowInfoContext316     GetCallingWindowInfoContext() : Context(nullptr, nullptr){};
operatorGetCallingWindowInfoContext317     napi_status operator()(napi_env env, napi_value *result) override
318     {
319         if (status_ != napi_ok) {
320             output_ = nullptr;
321             return status_;
322         }
323         return Context::operator()(env, result);
324     }
325 };
326 
327 struct SetPreviewTextContext : public AsyncCall::Context {
328     std::string text;
329     Range range;
SetPreviewTextContextSetPreviewTextContext330     SetPreviewTextContext() : Context(nullptr, nullptr){};
operatorSetPreviewTextContext331     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
332     {
333         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
334         return Context::operator()(env, argc, argv, self);
335     }
operatorSetPreviewTextContext336     napi_status operator()(napi_env env, napi_value *result) override
337     {
338         if (status_ != napi_ok) {
339             output_ = nullptr;
340             return status_;
341         }
342         return Context::operator()(env, result);
343     }
344 };
345 
346 struct FinishTextPreviewContext : public AsyncCall::Context {
FinishTextPreviewContextFinishTextPreviewContext347     FinishTextPreviewContext() : Context(nullptr, nullptr){};
operatorFinishTextPreviewContext348     napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
349     {
350         CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
351         return Context::operator()(env, argc, argv, self);
352     }
operatorFinishTextPreviewContext353     napi_status operator()(napi_env env, napi_value *result) override
354     {
355         if (status_ != napi_ok) {
356             output_ = nullptr;
357             return status_;
358         }
359         return Context::operator()(env, result);
360     }
361 };
362 
363 class JsTextInputClientEngine {
364 public:
365     JsTextInputClientEngine() = default;
366     ~JsTextInputClientEngine() = default;
367     static napi_value Init(napi_env env, napi_value info);
368     static napi_value SendKeyFunction(napi_env env, napi_callback_info info);
369     static napi_value DeleteForward(napi_env env, napi_callback_info info);
370     static napi_value DeleteBackward(napi_env env, napi_callback_info info);
371     static napi_value InsertText(napi_env env, napi_callback_info info);
372     static napi_value GetForward(napi_env env, napi_callback_info info);
373     static napi_value GetBackward(napi_env env, napi_callback_info info);
374     static napi_value MoveCursor(napi_env env, napi_callback_info info);
375     static napi_value GetEditorAttribute(napi_env env, napi_callback_info info);
376     static napi_value GetTextIndexAtCursor(napi_env env, napi_callback_info info);
377     static napi_value GetTextInputClientInstance(napi_env env);
378     static napi_value SelectByRange(napi_env env, napi_callback_info info);
379     static napi_value SelectByMovement(napi_env env, napi_callback_info info);
380     static napi_value SendExtendAction(napi_env env, napi_callback_info info);
381     static napi_value InsertTextSync(napi_env env, napi_callback_info info);
382     static napi_value MoveCursorSync(napi_env env, napi_callback_info info);
383     static napi_value GetEditorAttributeSync(napi_env env, napi_callback_info info);
384     static napi_value SelectByRangeSync(napi_env env, napi_callback_info info);
385     static napi_value SelectByMovementSync(napi_env env, napi_callback_info info);
386     static napi_value GetTextIndexAtCursorSync(napi_env env, napi_callback_info info);
387     static napi_value DeleteForwardSync(napi_env env, napi_callback_info info);
388     static napi_value DeleteBackwardSync(napi_env env, napi_callback_info info);
389     static napi_value GetForwardSync(napi_env env, napi_callback_info info);
390     static napi_value GetBackwardSync(napi_env env, napi_callback_info info);
391     static napi_value GetCallingWindowInfo(napi_env env, napi_callback_info info);
392     static napi_value SendPrivateCommand(napi_env env, napi_callback_info info);
393     static napi_value SetPreviewText(napi_env env, napi_callback_info info);
394     static napi_value SetPreviewTextSync(napi_env env, napi_callback_info info);
395     static napi_value FinishTextPreview(napi_env env, napi_callback_info info);
396     static napi_value FinishTextPreviewSync(napi_env env, napi_callback_info info);
397 
398 private:
399     static napi_status GetSelectRange(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt);
400     static napi_status GetSelectMovement(napi_env env, napi_value argv, std::shared_ptr<SelectContext> ctxt);
401 
402     static napi_value JsConstructor(napi_env env, napi_callback_info info);
403     static napi_value GetResult(napi_env env, std::string &text);
404     static napi_value GetResultEditorAttribute(
405         napi_env env, std::shared_ptr<GetEditorAttributeContext> getEditorAttribute);
406     static napi_value HandleParamCheckFailure(napi_env env);
407     static napi_status GetPreviewTextParam(napi_env env, size_t argc, napi_value *argv, std::string &text,
408         Range &range);
409 
410     static const std::string TIC_CLASS_NAME;
411     static thread_local napi_ref TICRef_;
412     static std::shared_ptr<AsyncCall::TaskQueue> taskQueue_;
413     static BlockQueue<PrivateCommandInfo> privateCommandQueue_;
GenerateTraceId()414     static std::string GenerateTraceId()
415     {
416         auto traceId = traceId_++;
417         return std::to_string(traceId);
418     }
419     static uint32_t traceId_;
420 };
421 } // namespace MiscServices
422 } // namespace OHOS
423 #endif // INTERFACE_KITS_JS_NAPI_INPUTMETHODENGINE_INCLUDE_JS_TEXT_INPUT_CLIENT_H