1 /*
2  * Copyright (c) 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 #include "enable_ime_data_parser.h"
17 
18 #include "ime_info_inquirer.h"
19 #include "iservice_registry.h"
20 #include "serializable.h"
21 #include "settings_data_utils.h"
22 #include "system_ability_definition.h"
23 
24 namespace OHOS {
25 namespace MiscServices {
26 std::mutex EnableImeDataParser::instanceMutex_;
27 sptr<EnableImeDataParser> EnableImeDataParser::instance_ = nullptr;
~EnableImeDataParser()28 EnableImeDataParser::~EnableImeDataParser()
29 {
30 }
31 
GetInstance()32 sptr<EnableImeDataParser> EnableImeDataParser::GetInstance()
33 {
34     if (instance_ == nullptr) {
35         std::lock_guard<std::mutex> autoLock(instanceMutex_);
36         if (instance_ == nullptr) {
37             IMSA_HILOGI("need to create instance.");
38             instance_ = new (std::nothrow) EnableImeDataParser();
39             if (instance_ == nullptr) {
40                 IMSA_HILOGE("instance is nullptr!");
41                 return instance_;
42             }
43         }
44     }
45     return instance_;
46 }
47 
Initialize(const int32_t userId)48 int32_t EnableImeDataParser::Initialize(const int32_t userId)
49 {
50     currentUserId_ = userId;
51     {
52         std::lock_guard<std::mutex> autoLock(listMutex_);
53         enableList_.insert({ std::string(ENABLE_IME), {} });
54         enableList_.insert({ std::string(ENABLE_KEYBOARD), {} });
55     }
56     UpdateEnableData(userId, ENABLE_IME);
57     UpdateEnableData(userId, ENABLE_KEYBOARD);
58     GetDefaultIme();
59     return ErrorCode::NO_ERROR;
60 }
61 
OnUserChanged(const int32_t targetUserId)62 void EnableImeDataParser::OnUserChanged(const int32_t targetUserId)
63 {
64     currentUserId_ = targetUserId;
65     UpdateEnableData(targetUserId, ENABLE_IME);
66     UpdateEnableData(targetUserId, ENABLE_KEYBOARD);
67 }
68 
CheckNeedSwitch(const std::string & key,SwitchInfo & switchInfo,const int32_t userId)69 bool EnableImeDataParser::CheckNeedSwitch(const std::string &key, SwitchInfo &switchInfo, const int32_t userId)
70 {
71     IMSA_HILOGD("start, data changed.");
72     auto currentIme = ImeInfoInquirer::GetInstance().GetCurrentInputMethod(userId);
73     auto defaultIme = GetDefaultIme();
74     if (defaultIme == nullptr) {
75         IMSA_HILOGE("defaultIme is nullptr!");
76         return false;
77     }
78     switchInfo.bundleName = defaultIme->name;
79     switchInfo.subName = "";
80     if (currentIme == nullptr) {
81         IMSA_HILOGE("currentIme is nullptr!");
82         return true;
83     }
84     if (key == std::string(ENABLE_IME)) {
85         if (currentIme->name == defaultIme->name) {
86             std::lock_guard<std::mutex> autoLock(listMutex_);
87             GetEnableData(key, enableList_[key], userId);
88             IMSA_HILOGD("current ime is default, do not need switch ime.");
89             return false;
90         }
91         return CheckTargetEnableName(key, currentIme->name, switchInfo.bundleName, userId);
92     } else if (key == std::string(ENABLE_KEYBOARD)) {
93         if (currentIme->name != defaultIme->name || currentIme->id == defaultIme->id) {
94             IMSA_HILOGD("current ime is not default or id is default.");
95             std::lock_guard<std::mutex> autoLock(listMutex_);
96             GetEnableData(key, enableList_[key], userId);
97             return false;
98         }
99         switchInfo.subName = defaultIme->id;
100         return CheckTargetEnableName(key, currentIme->id, switchInfo.subName, userId);
101     }
102     IMSA_HILOGW("invalid key: %{public}s.", key.c_str());
103     return false;
104 }
105 
CheckNeedSwitch(const SwitchInfo & info,const int32_t userId)106 bool EnableImeDataParser::CheckNeedSwitch(const SwitchInfo &info, const int32_t userId)
107 {
108     IMSA_HILOGD("current userId: %{public}d, target userId: %{public}d, check bundleName: %{public}s", currentUserId_,
109         userId, info.bundleName.c_str());
110     if (info.bundleName == GetDefaultIme()->name) {
111         IMSA_HILOGD("default ime, permit to switch");
112         return true;
113     }
114     IMSA_HILOGD("check ime.");
115     std::vector<std::string> tempVec;
116     int32_t tempRet = GetEnableData(TEMP_IME, tempVec, userId);
117     if (tempRet != ErrorCode::NO_ERROR || tempVec.empty()) {
118         IMSA_HILOGD("get tempVec list failed, or tempVec list is empty.");
119     } else {
120         auto iter = std::find_if(
121             tempVec.begin(), tempVec.end(), [&info](const std::string &ime) { return info.bundleName == ime; });
122         if (iter != tempVec.end()) {
123             IMSA_HILOGD("In tempVec list.");
124             return true;
125         }
126     }
127     std::vector<std::string> enableVec;
128     int32_t ret = GetEnableData(ENABLE_IME, enableVec, userId);
129     if (ret != ErrorCode::NO_ERROR || enableVec.empty()) {
130         IMSA_HILOGD("get enable list failed, or enable list is empty.");
131         return false;
132     }
133 
134     auto iter = std::find_if(
135         enableVec.begin(), enableVec.end(), [&info](const std::string &ime) { return info.bundleName == ime; });
136     if (iter != enableVec.end()) {
137         IMSA_HILOGD("in enable list.");
138         return true;
139     }
140     return false;
141 }
142 
CheckTargetEnableName(const std::string & key,const std::string & targetName,std::string & nextIme,const int32_t userId)143 bool EnableImeDataParser::CheckTargetEnableName(
144     const std::string &key, const std::string &targetName, std::string &nextIme, const int32_t userId)
145 {
146     IMSA_HILOGD("start.");
147     std::vector<std::string> enableVec;
148     int32_t ret = GetEnableData(key, enableVec, userId);
149     if (ret != ErrorCode::NO_ERROR) {
150         IMSA_HILOGE("get enable list abnormal.");
151         return false;
152     }
153 
154     if (enableVec.empty()) {
155         IMSA_HILOGE("enable empty, switch default ime.");
156         return true;
157     }
158     std::lock_guard<std::mutex> autoLock(listMutex_);
159     auto iter = std::find_if(
160         enableVec.begin(), enableVec.end(), [&targetName](const std::string &ime) { return ime == targetName; });
161     if (iter != enableVec.end()) {
162         IMSA_HILOGD("enable list has current ime, do not need switch.");
163         enableList_[key].assign(enableVec.begin(), enableVec.end());
164         return false;
165     }
166 
167     auto it = std::find_if(enableList_[key].begin(), enableList_[key].end(),
168         [&targetName](const std::string &ime) { return ime == targetName; });
169     if (it == enableList_[key].end()) {
170         enableList_[key].assign(enableVec.begin(), enableVec.end());
171         return true;
172     }
173 
174     std::rotate(enableList_[key].begin(), it, enableList_[key].end());
175     auto result =
176         std::find_first_of(enableList_[key].begin(), enableList_[key].end(), enableVec.begin(), enableVec.end());
177     if (result != enableList_[key].end()) {
178         IMSA_HILOGD("found the next cached ime in enable ime list.");
179         nextIme = *result;
180     }
181     enableList_[key].assign(enableVec.begin(), enableVec.end());
182     return true;
183 }
184 
CoverGlobalTable(const std::string & key,std::string & valueStr)185 void EnableImeDataParser::CoverGlobalTable(const std::string &key, std::string &valueStr)
186 {
187     SettingsDataUtils::GetInstance()->SetStringValue(SETTING_URI_PROXY, key, valueStr);
188 }
189 
GetUserEnableTable(int32_t userId,const std::string & key)190 std::string EnableImeDataParser::GetUserEnableTable(int32_t userId, const std::string &key)
191 {
192     std::string valueStr;
193     int32_t ret = SettingsDataUtils::GetInstance()->GetStringValue(
194         SETTINGS_USER_DATA_URI + std::to_string(userId) + "?Proxy=true", key, valueStr);
195     IMSA_HILOGI("get user enable table, userId = %{public}d, ret = %{public}d, valurStr = %{public}s",
196         userId, ret, valueStr.c_str());
197     if (valueStr.empty()) {
198         auto defaultIme = GetDefaultIme();
199         if (defaultIme != nullptr) {
200             valueStr =
201               "{\"enableImeList\" : {\"" + std::to_string(userId) + "\" : [\"" + defaultIme->name + "\"]}}";
202         }
203     }
204     return valueStr;
205 }
206 
GetEanbleIme(int32_t userId,const std::string & key,const std::string & globalStr)207 std::string EnableImeDataParser::GetEanbleIme(int32_t userId, const std::string &key, const std::string &globalStr)
208 {
209     std::string enableStr = globalStr;
210     std::string globaleUserId;
211     if (enableStr.empty()) {
212         enableStr = GetUserEnableTable(currentUserId_, key);
213         CoverGlobalTable(key, enableStr);
214         globaleUserId = std::to_string(currentUserId_);
215     } else {
216         globaleUserId = GetGlobalTableUserId(enableStr);
217     }
218     SettingsDataUtils::GetInstance()->SetStringValue(SETTINGS_USER_DATA_URI + globaleUserId + "?Proxy=true",
219         key, enableStr);
220     if (globaleUserId != std::to_string(currentUserId_)) {
221         enableStr = GetUserEnableTable(currentUserId_, key);
222         CoverGlobalTable(key, enableStr);
223     }
224     if (currentUserId_ != userId) {
225         enableStr = GetUserEnableTable(userId, key);
226     }
227     return enableStr;
228 }
229 
GetEnableData(const std::string & key,std::vector<std::string> & enableVec,const int32_t userId)230 int32_t EnableImeDataParser::GetEnableData(
231     const std::string &key, std::vector<std::string> &enableVec, const int32_t userId)
232 {
233     if (key != std::string(ENABLE_IME) && key != std::string(ENABLE_KEYBOARD) && key != std::string(TEMP_IME)) {
234         IMSA_HILOGD("invalid key: %{public}s.", key.c_str());
235         return ErrorCode::ERROR_ENABLE_IME;
236     }
237 
238     IMSA_HILOGD("userId: %{public}d, key: %{public}s.", userId, key.c_str());
239     std::string valueStr;
240     int32_t ret = SettingsDataUtils::GetInstance()->GetStringValue(SETTING_URI_PROXY, key, valueStr);
241     if (ret == ErrorCode::ERROR_KEYWORD_NOT_FOUND) {
242         IMSA_HILOGW("no keyword exist");
243         enableVec.clear();
244         return ErrorCode::NO_ERROR;
245     }
246     if (key != ENABLE_IME && (ret != ErrorCode::NO_ERROR || valueStr.empty())) {
247         IMSA_HILOGW("get value failed, or valueStr is empty.");
248         return ErrorCode::ERROR_ENABLE_IME;
249     }
250     auto parseRet = false;
251     if (key == ENABLE_IME) {
252         valueStr = GetEanbleIme(userId, key, valueStr);
253         if (valueStr.empty()) {
254             IMSA_HILOGW("valueStr is empty, userId = %{public}d", userId);
255             return ErrorCode::NO_ERROR;
256         }
257         parseRet = ParseEnableIme(valueStr, userId, enableVec);
258     }
259     if (key == ENABLE_KEYBOARD) {
260         parseRet = ParseEnableKeyboard(valueStr, userId, enableVec);
261     }
262     if (key == TEMP_IME) {
263         parseRet = ParseTempIme(valueStr, userId, enableVec);
264     }
265     return parseRet ? ErrorCode::NO_ERROR : ErrorCode::ERROR_ENABLE_IME;
266 }
267 
GetGlobalTableUserId(const std::string & valueStr)268 std::string EnableImeDataParser::GetGlobalTableUserId(const std::string &valueStr)
269 {
270     auto root = cJSON_Parse(valueStr.c_str());
271     auto subNode = Serializable::GetSubNode(root, "enableImeList");
272     if (subNode == nullptr || cJSON_IsObject(subNode)) {
273         IMSA_HILOGW("subNode is null or not object");
274         return "";
275     }
276     if (subNode->child == nullptr) {
277         IMSA_HILOGW("subNode has not child");
278         return "";
279     }
280     return subNode->child->string;
281 }
282 
ParseTempIme(const std::string & valueStr,int32_t userId,std::vector<std::string> & tempVector)283 bool EnableImeDataParser::ParseTempIme(const std::string &valueStr, int32_t userId,
284     std::vector<std::string> &tempVector)
285 {
286     TempImeCfg tempIme;
287     tempIme.tempImeList.userId = std::to_string(userId);
288     auto ret = tempIme.Unmarshall(valueStr);
289     if (!ret) {
290         return ret;
291     }
292     tempVector = tempIme.tempImeList.identities;
293     return true;
294 }
295 
ParseEnableIme(const std::string & valueStr,int32_t userId,std::vector<std::string> & enableVec)296 bool EnableImeDataParser::ParseEnableIme(
297     const std::string &valueStr, int32_t userId, std::vector<std::string> &enableVec)
298 {
299     EnableImeCfg enableIme;
300     enableIme.userImeCfg.userId = std::to_string(userId);
301     auto ret = enableIme.Unmarshall(valueStr);
302     if (!ret) {
303         return ret;
304     }
305     enableVec = enableIme.userImeCfg.identities;
306     return true;
307 }
308 
ParseEnableKeyboard(const std::string & valueStr,int32_t userId,std::vector<std::string> & enableVec)309 bool EnableImeDataParser::ParseEnableKeyboard(
310     const std::string &valueStr, int32_t userId, std::vector<std::string> &enableVec)
311 {
312     EnableKeyBoardCfg enableKeyboard;
313     enableKeyboard.userImeCfg.userId = std::to_string(userId);
314     auto ret = enableKeyboard.Unmarshall(valueStr);
315     if (!ret) {
316         return ret;
317     }
318     enableVec = enableKeyboard.userImeCfg.identities;
319     return true;
320 }
321 
GetDefaultIme()322 std::shared_ptr<Property> EnableImeDataParser::GetDefaultIme()
323 {
324     std::lock_guard<std::mutex> lock(defaultImeMutex_);
325     if (defaultImeInfo_ == nullptr) {
326         defaultImeInfo_ = std::make_shared<Property>();
327     }
328     if (!defaultImeInfo_->name.empty() && !defaultImeInfo_->id.empty()) {
329         IMSA_HILOGD("defaultImeInfo_ has cached default time: %{public}s.", defaultImeInfo_->name.c_str());
330         return defaultImeInfo_;
331     }
332 
333     auto defaultIme = ImeInfoInquirer::GetInstance().GetDefaultImeCfgProp();
334     if (defaultIme == nullptr) {
335         IMSA_HILOGE("defaultIme is nullptr!");
336         return defaultImeInfo_;
337     }
338     defaultImeInfo_->name = defaultIme->name;
339     defaultImeInfo_->id = defaultIme->id;
340     return defaultImeInfo_;
341 }
342 
OnConfigChanged(int32_t userId,const std::string & key)343 void EnableImeDataParser::OnConfigChanged(int32_t userId, const std::string &key)
344 {
345     UpdateEnableData(userId, key);
346 }
347 
UpdateEnableData(int32_t userId,const std::string & key)348 int32_t EnableImeDataParser::UpdateEnableData(int32_t userId, const std::string &key)
349 {
350     std::lock_guard<std::mutex> autoLock(listMutex_);
351     if (key == ENABLE_IME) {
352         isEnableImeInit_ = false;
353     }
354     std::vector<std::string> enableData;
355     IMSA_HILOGD("update userId: %{public}d %{public}s", userId, key.c_str());
356     auto ret = GetEnableData(key, enableData, userId);
357     if (ret != ErrorCode::NO_ERROR) {
358         IMSA_HILOGE("userId: %{public}d get enable %{public}s list failed!", userId, key.c_str());
359         return ret;
360     }
361     enableList_.insert_or_assign(key, enableData);
362     if (key == ENABLE_IME) {
363         isEnableImeInit_ = true;
364     }
365     return ErrorCode::NO_ERROR;
366 }
367 
GetEnableIme(int32_t userId,std::vector<std::string> & enableVec)368 int32_t EnableImeDataParser::GetEnableIme(int32_t userId, std::vector<std::string> &enableVec)
369 {
370     if (userId != currentUserId_) {
371         return GetEnableData(ENABLE_IME, enableVec, userId);
372     }
373     auto ret = GetEnableImeFromCache(enableVec);
374     if (ret == ErrorCode::NO_ERROR) {
375         return ErrorCode::NO_ERROR;
376     }
377     ret = UpdateEnableData(userId, ENABLE_IME);
378     if (ret != ErrorCode::NO_ERROR) {
379         return ret;
380     }
381     return GetEnableImeFromCache(enableVec);
382 }
383 
GetEnableImeFromCache(std::vector<std::string> & enableVec)384 int32_t EnableImeDataParser::GetEnableImeFromCache(std::vector<std::string> &enableVec)
385 {
386     std::lock_guard<std::mutex> autoLock(listMutex_);
387     if (isEnableImeInit_) {
388         auto it = enableList_.find(ENABLE_IME);
389         if (it != enableList_.end()) {
390             IMSA_HILOGD("GetEnableIme from cache.");
391             enableVec = it->second;
392             return ErrorCode::NO_ERROR;
393         }
394     }
395     return ErrorCode::ERROR_ENABLE_IME;
396 }
397 } // namespace MiscServices
398 } // namespace OHOS