• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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