1 /*
2 * Copyright (c) 2025 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 #include "interfaces/napi/kits/utils/napi_utils.h"
17
18 #include "frameworks/core/common/ace_application_info.h"
19 #include "frameworks/core/components_ng/pattern/select_overlay/select_overlay_property.h"
20
21 namespace OHOS::Ace::Napi {
22
GetDisableFlag(const std::string & id)23 static NG::SystemServiceMenuDisableFlag GetDisableFlag(const std::string& id)
24 {
25 static std::unordered_map<std::string, NG::SystemServiceMenuDisableFlag> disalbeFlagsMap = {
26 { NG::OH_DEFAULT_TRANSLATE, NG::DISABLE_TRANSLATE_FLAG },
27 { NG::OH_DEFAULT_SEARCH, NG::DISABLE_SEARCH_FLAG },
28 { NG::OH_DEFAULT_SHARE, NG::DISABLE_SHARE_FLAG },
29 { NG::OH_DEFAULT_CAMERA_INPUT, NG::DISABLE_CAMERA_INPUT_FLAG },
30 { NG::OH_DEFAULT_AI_WRITE, NG::DISABLE_AI_WRITER_FLAG },
31 { NG::OH_DEFAULT_COLLABORATION_SERVICE, NG::DISABLE_COLLABORATION_SERVICE_FLAG },
32 { NG::OH_DEFAULT_AI_MENU_URL, NG::DISABLE_AI_MENU_URL_FLAG },
33 { NG::OH_DEFAULT_AI_MENU_PHONE, NG::DISABLE_AI_MENU_PHONE_FLAG },
34 { NG::OH_DEFAULT_AI_MENU_EMAIL, NG::DISABLE_AI_MENU_EMAIL_FLAG },
35 { NG::OH_DEFAULT_AI_MENU_ADDRESS, NG::DISABLE_AI_MENU_ADDRESS_FLAG },
36 { NG::OH_DEFAULT_AI_MENU_DATETIME, NG::DISABLE_AI_MENU_DATETIME_FLAG },
37 { NG::OH_DEFAULT_ASK_CELIA, NG::DISABLE_ASK_CELIA_FLAG },
38 };
39 return disalbeFlagsMap.find(id) == disalbeFlagsMap.end() ? NG::DISABLE_NORMAL_FLAG : disalbeFlagsMap[id];
40 }
41
DisableSystemServiceMenuItems(bool disableAll)42 static void DisableSystemServiceMenuItems(bool disableAll)
43 {
44 auto textMenuInfo = AceApplicationInfo::GetInstance().GetTextMenuInfo();
45 auto isPrevDisableAll = (textMenuInfo.disableFlags & NG::DISABLE_ALL_FLAG) == NG::DISABLE_ALL_FLAG;
46 if (disableAll) {
47 AceApplicationInfo::GetInstance().AddTextMenuDisableFlag(NG::DISABLE_ALL_FLAG);
48 } else {
49 AceApplicationInfo::GetInstance().SetTextMenuDisableFlags(~NG::DISABLE_ALL_FLAG);
50 }
51 if (isPrevDisableAll != disableAll && textMenuInfo.menuOnChangeCallback) {
52 if (!textMenuInfo.menuOnChangeCallback()) {
53 AceApplicationInfo::GetInstance().SetTextMenuOnChangeCallback(nullptr);
54 }
55 }
56 }
57
DisableTextMenuSystemItems(const std::vector<std::string> & menuItems)58 static void DisableTextMenuSystemItems(const std::vector<std::string>& menuItems)
59 {
60 auto textMenuInfo = AceApplicationInfo::GetInstance().GetTextMenuInfo();
61 auto oldFlags = textMenuInfo.disableFlags;
62 AceApplicationInfo::GetInstance().SetTextMenuDisableFlags(NG::DISABLE_ALL_FLAG);
63 for (const auto& item : menuItems) {
64 AceApplicationInfo::GetInstance().AddTextMenuDisableFlag(GetDisableFlag(item));
65 }
66 if (oldFlags != AceApplicationInfo::GetInstance().GetTextMenuInfo().disableFlags &&
67 textMenuInfo.menuOnChangeCallback) {
68 if (!textMenuInfo.menuOnChangeCallback()) {
69 AceApplicationInfo::GetInstance().SetTextMenuOnChangeCallback(nullptr);
70 }
71 }
72 }
73
JSDisableSystemServiceMenuItems(napi_env env,napi_callback_info info)74 static napi_value JSDisableSystemServiceMenuItems(napi_env env, napi_callback_info info)
75 {
76 napi_handle_scope scope = nullptr;
77 napi_open_handle_scope(env, &scope);
78 CHECK_NULL_RETURN(scope, nullptr);
79 napi_status status;
80 size_t argc = 1;
81 napi_value argv[1];
82 napi_value thisvar = nullptr;
83 void* data = nullptr;
84 status = napi_get_cb_info(env, info, &argc, argv, &thisvar, &data);
85 if (status != napi_ok || argc < 1) {
86 TAG_LOGE(AceLogTag::ACE_SELECT_OVERLAY, "Invalid arguments.");
87 napi_close_handle_scope(env, scope);
88 return nullptr;
89 }
90 napi_valuetype valueType = napi_undefined;
91 status = napi_typeof(env, argv[0], &valueType);
92 if (status != napi_ok || valueType != napi_boolean) {
93 TAG_LOGE(AceLogTag::ACE_SELECT_OVERLAY, "Expected boolean.");
94 DisableSystemServiceMenuItems(false);
95 napi_close_handle_scope(env, scope);
96 return nullptr;
97 }
98 bool disableAll = false;
99 status = napi_get_value_bool(env, argv[0], &disableAll);
100 if (status == napi_ok) {
101 DisableSystemServiceMenuItems(disableAll);
102 } else {
103 TAG_LOGE(AceLogTag::ACE_SELECT_OVERLAY, "Failed to get boolean value.");
104 }
105 napi_close_handle_scope(env, scope);
106 return nullptr;
107 }
108
GetStringLength(napi_env env,napi_value str)109 static size_t GetStringLength(napi_env env, napi_value str)
110 {
111 size_t buffSize = 0;
112 napi_status status = napi_get_value_string_utf8(env, str, nullptr, 0, &buffSize);
113 if (status != napi_ok || buffSize == 0) {
114 return 0;
115 }
116 return buffSize;
117 }
118
ParseTextMenuItems(std::vector<std::string> & items,napi_env env,napi_value value,uint32_t length)119 static void ParseTextMenuItems(std::vector<std::string>& items, napi_env env, napi_value value, uint32_t length)
120 {
121 napi_status status;
122 for (uint32_t i = 0; i < length; i++) {
123 napi_value element;
124 status = napi_get_element(env, value, i, &element);
125 if (status != napi_ok) {
126 continue;
127 }
128 napi_valuetype valueType = napi_undefined;
129 status = napi_typeof(env, element, &valueType);
130 if (status != napi_ok || valueType != napi_object) {
131 continue;
132 }
133 napi_value idValue;
134 status = napi_get_named_property(env, element, "id_", &idValue);
135 if (status != napi_ok) {
136 continue;
137 }
138 status = napi_typeof(env, idValue, &valueType);
139 if (status != napi_ok || valueType != napi_string) {
140 continue;
141 }
142 size_t strLen = GetStringLength(env, idValue) + 1;
143 std::unique_ptr<char[]> idString = std::make_unique<char[]>(strLen);
144 size_t resultLen;
145 napi_get_value_string_utf8(env, idValue, idString.get(), strLen, &resultLen);
146 items.emplace_back(idString.get());
147 }
148 }
149
JSDisableMenuItems(napi_env env,napi_callback_info info)150 static napi_value JSDisableMenuItems(napi_env env, napi_callback_info info)
151 {
152 napi_handle_scope scope = nullptr;
153 napi_open_handle_scope(env, &scope);
154 CHECK_NULL_RETURN(scope, nullptr);
155 napi_status status;
156 size_t argc = 1;
157 napi_value argv[1];
158 napi_value thisvar = nullptr;
159 void* data = nullptr;
160 status = napi_get_cb_info(env, info, &argc, argv, &thisvar, &data);
161 if (status != napi_ok || argc < 1) {
162 TAG_LOGE(AceLogTag::ACE_SELECT_OVERLAY, "Invalid arguments.");
163 napi_close_handle_scope(env, scope);
164 return nullptr;
165 }
166 bool isArray = false;
167 status = napi_is_array(env, argv[0], &isArray);
168 if (status != napi_ok || !isArray) {
169 TAG_LOGE(AceLogTag::ACE_SELECT_OVERLAY, "Invalid argument type.");
170 DisableTextMenuSystemItems({});
171 napi_close_handle_scope(env, scope);
172 return nullptr;
173 }
174 uint32_t length = 0;
175 status = napi_get_array_length(env, argv[0], &length);
176 if (status != napi_ok) {
177 TAG_LOGE(AceLogTag::ACE_SELECT_OVERLAY, "Failed to get array length.");
178 napi_close_handle_scope(env, scope);
179 return nullptr;
180 }
181 std::vector<std::string> menuItems;
182 ParseTextMenuItems(menuItems, env, argv[0], length);
183 DisableTextMenuSystemItems(menuItems);
184 napi_close_handle_scope(env, scope);
185 return nullptr;
186 }
187
textMenuControllerExport(napi_env env,napi_value exports)188 static napi_value textMenuControllerExport(napi_env env, napi_value exports)
189 {
190 napi_property_descriptor textMenuControllerDesc[] = {
191 DECLARE_NAPI_FUNCTION("disableSystemServiceMenuItems", JSDisableSystemServiceMenuItems),
192 DECLARE_NAPI_FUNCTION("disableMenuItems", JSDisableMenuItems),
193 };
194 NAPI_CALL(env, napi_define_properties(env, exports,
195 sizeof(textMenuControllerDesc) / sizeof(textMenuControllerDesc[0]), textMenuControllerDesc));
196
197 return exports;
198 }
199
200 static napi_module textMenuControllerModule = {
201 .nm_version = 1,
202 .nm_flags = 0,
203 .nm_filename = nullptr,
204 .nm_register_func = textMenuControllerExport,
205 .nm_modname = "arkui.textMenuController",
206 .nm_priv = ((void*)0),
207 .reserved = { 0 },
208 };
209
TextMenuControllerRegister()210 extern "C" __attribute__((constructor)) void TextMenuControllerRegister()
211 {
212 napi_module_register(&textMenuControllerModule);
213 }
214 } // namespace OHOS::Ace::Napi
215