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 #include "sec_comp_base.h"
16 
17 #include "sec_comp_err.h"
18 #include "sec_comp_log.h"
19 
20 namespace OHOS {
21 namespace Security {
22 namespace SecurityComponent {
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, SECURITY_DOMAIN_SECURITY_COMPONENT, "SecCompBase"};
25 }
26 
27 const std::string JsonTagConstants::JSON_RECT = "rect";
28 const std::string JsonTagConstants::JSON_SC_TYPE = "type";
29 const std::string JsonTagConstants::JSON_NODE_ID = "nodeId";
30 const std::string JsonTagConstants::JSON_RECT_X = "x";
31 const std::string JsonTagConstants::JSON_RECT_Y = "y";
32 const std::string JsonTagConstants::JSON_RECT_WIDTH = "width";
33 const std::string JsonTagConstants::JSON_RECT_HEIGHT = "height";
34 const std::string JsonTagConstants::JSON_WINDOW_RECT = "windowRect";
35 const std::string JsonTagConstants::JSON_SIZE_TAG = "size";
36 const std::string JsonTagConstants::JSON_FONT_SIZE_TAG = "fontSize";
37 const std::string JsonTagConstants::JSON_ICON_SIZE_TAG = "iconSize";
38 const std::string JsonTagConstants::JSON_PADDING_SIZE_TAG = "paddingSize";
39 const std::string JsonTagConstants::JSON_PADDING_LEFT_TAG = "left";
40 const std::string JsonTagConstants::JSON_PADDING_TOP_TAG = "top";
41 const std::string JsonTagConstants::JSON_PADDING_RIGHT_TAG = "right";
42 const std::string JsonTagConstants::JSON_PADDING_BOTTOM_TAG = "bottom";
43 const std::string JsonTagConstants::JSON_TEXT_ICON_PADDING_TAG = "textIconSpace";
44 const std::string JsonTagConstants::JSON_RECT_WIDTH_TAG = "width";
45 const std::string JsonTagConstants::JSON_RECT_HEIGHT_TAG = "height";
46 const std::string JsonTagConstants::JSON_COLORS_TAG = "colors";
47 const std::string JsonTagConstants::JSON_FONT_COLOR_TAG = "fontColor";
48 const std::string JsonTagConstants::JSON_ICON_COLOR_TAG = "iconColor";
49 const std::string JsonTagConstants::JSON_BG_COLOR_TAG = "bgColor";
50 const std::string JsonTagConstants::JSON_BORDER_TAG = "border";
51 const std::string JsonTagConstants::JSON_BORDER_WIDTH_TAG = "borderWidth";
52 const std::string JsonTagConstants::JSON_PARENT_TAG = "parent";
53 const std::string JsonTagConstants::JSON_PARENT_EFFECT_TAG = "parentEffect";
54 const std::string JsonTagConstants::JSON_IS_CLIPPED_TAG = "isClipped";
55 const std::string JsonTagConstants::JSON_TOP_CLIP_TAG = "topClip";
56 const std::string JsonTagConstants::JSON_BOTTOM_CLIP_TAG = "bottomClip";
57 const std::string JsonTagConstants::JSON_LEFT_CLIP_TAG = "leftClip";
58 const std::string JsonTagConstants::JSON_RIGHT_CLIP_TAG = "rightClip";
59 const std::string JsonTagConstants::JSON_PARENT_TAG_TAG = "parentTag";
60 const std::string JsonTagConstants::JSON_STYLE_TAG = "style";
61 const std::string JsonTagConstants::JSON_TEXT_TAG = "text";
62 const std::string JsonTagConstants::JSON_ICON_TAG = "icon";
63 const std::string JsonTagConstants::JSON_BG_TAG = "bg";
64 const std::string JsonTagConstants::JSON_WINDOW_ID = "windowId";
65 
ParseDimension(const nlohmann::json & json,const std::string & tag,DimensionT & res)66 bool SecCompBase::ParseDimension(const nlohmann::json& json, const std::string& tag, DimensionT& res)
67 {
68     if ((json.find(tag) == json.end()) || !json.at(tag).is_number_float()) {
69         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
70         return false;
71     }
72 
73     res = json.at(tag).get<double>();
74     return true;
75 }
76 
ParseColor(const nlohmann::json & json,const std::string & tag,SecCompColor & res)77 bool SecCompBase::ParseColor(const nlohmann::json& json, const std::string& tag, SecCompColor& res)
78 {
79     if ((json.find(tag) == json.end()) || !json.at(tag).is_number()) {
80         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
81         return false;
82     }
83 
84     res.value = json.at(tag).get<uint32_t>();
85     return true;
86 }
87 
ParseBool(const nlohmann::json & json,const std::string & tag,bool & res)88 bool SecCompBase::ParseBool(const nlohmann::json& json, const std::string& tag, bool& res)
89 {
90     if ((json.find(tag) == json.end()) || !json.at(tag).is_boolean()) {
91         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
92         return false;
93     }
94 
95     res = json.at(tag).get<bool>();
96     return true;
97 }
98 
ParseString(const nlohmann::json & json,const std::string & tag,std::string & res)99 bool SecCompBase::ParseString(const nlohmann::json& json, const std::string& tag, std::string& res)
100 {
101     if ((json.find(tag) == json.end()) || !json.at(tag).is_string()) {
102         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
103         return false;
104     }
105 
106     res = json.at(tag).get<std::string>();
107     return true;
108 }
109 
ParsePadding(const nlohmann::json & json,const std::string & tag,PaddingSize & res)110 bool SecCompBase::ParsePadding(const nlohmann::json& json, const std::string& tag, PaddingSize& res)
111 {
112     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
113         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
114         return false;
115     }
116 
117     auto jsonPadding = json.at(tag);
118     if (!ParseDimension(jsonPadding, JsonTagConstants::JSON_PADDING_TOP_TAG, res.top)) {
119         return false;
120     }
121     if (!ParseDimension(jsonPadding, JsonTagConstants::JSON_PADDING_RIGHT_TAG, res.right)) {
122         return false;
123     }
124     if (!ParseDimension(jsonPadding, JsonTagConstants::JSON_PADDING_BOTTOM_TAG, res.bottom)) {
125         return false;
126     }
127     if (!ParseDimension(jsonPadding, JsonTagConstants::JSON_PADDING_LEFT_TAG, res.left)) {
128         return false;
129     }
130     return true;
131 }
132 
ParseColors(const nlohmann::json & json,const std::string & tag)133 bool SecCompBase::ParseColors(const nlohmann::json& json, const std::string& tag)
134 {
135     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
136         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
137         return false;
138     }
139     auto jsonColors = json.at(tag);
140     if (!ParseColor(jsonColors, JsonTagConstants::JSON_FONT_COLOR_TAG, fontColor_)) {
141         return false;
142     }
143     if (!ParseColor(jsonColors, JsonTagConstants::JSON_ICON_COLOR_TAG, iconColor_)) {
144         return false;
145     }
146     if (!ParseColor(jsonColors, JsonTagConstants::JSON_BG_COLOR_TAG, bgColor_)) {
147         return false;
148     }
149     return true;
150 }
151 
ParseBorders(const nlohmann::json & json,const std::string & tag)152 bool SecCompBase::ParseBorders(const nlohmann::json& json, const std::string& tag)
153 {
154     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
155         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
156         return false;
157     }
158     auto jsonBorder = json.at(tag);
159     return ParseDimension(jsonBorder, JsonTagConstants::JSON_BORDER_WIDTH_TAG, borderWidth_);
160 }
161 
ParseSize(const nlohmann::json & json,const std::string & tag)162 bool SecCompBase::ParseSize(const nlohmann::json& json, const std::string& tag)
163 {
164     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
165         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
166         return false;
167     }
168 
169     auto jsonSize = json.at(tag);
170     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_FONT_SIZE_TAG, fontSize_)) {
171         return false;
172     }
173 
174     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_ICON_SIZE_TAG, iconSize_)) {
175         return false;
176     }
177 
178     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_TEXT_ICON_PADDING_TAG, textIconSpace_)) {
179         return false;
180     }
181 
182     if (!ParsePadding(jsonSize, JsonTagConstants::JSON_PADDING_SIZE_TAG, padding_)) {
183         return false;
184     }
185 
186     return true;
187 }
188 
ParseParent(const nlohmann::json & json,const std::string & tag)189 bool SecCompBase::ParseParent(const nlohmann::json& json, const std::string& tag)
190 {
191     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
192         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
193         return false;
194     }
195     auto jsonParent = json.at(tag);
196     if (!ParseBool(jsonParent, JsonTagConstants::JSON_PARENT_EFFECT_TAG, parentEffect_)) {
197         return false;
198     }
199     if (!ParseBool(jsonParent, JsonTagConstants::JSON_IS_CLIPPED_TAG, isClipped_)) {
200         return false;
201     }
202     if (!ParseDimension(jsonParent, JsonTagConstants::JSON_TOP_CLIP_TAG, topClip_)) {
203         return false;
204     }
205     if (!ParseDimension(jsonParent, JsonTagConstants::JSON_BOTTOM_CLIP_TAG, bottomClip_)) {
206         return false;
207     }
208     if (!ParseDimension(jsonParent, JsonTagConstants::JSON_LEFT_CLIP_TAG, leftClip_)) {
209         return false;
210     }
211     if (!ParseDimension(jsonParent, JsonTagConstants::JSON_RIGHT_CLIP_TAG, rightClip_)) {
212         return false;
213     }
214     if (!ParseString(jsonParent, JsonTagConstants::JSON_PARENT_TAG_TAG, parentTag_)) {
215         return false;
216     }
217     return true;
218 }
219 
ParseRect(const nlohmann::json & json,const std::string & tag,SecCompRect & rect)220 bool SecCompBase::ParseRect(const nlohmann::json& json, const std::string& tag, SecCompRect& rect)
221 {
222     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
223         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
224         return false;
225     }
226 
227     auto jsonSize = json.at(tag);
228     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_RECT_X, rect.x_)) {
229         return false;
230     }
231 
232     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_RECT_Y, rect.y_)) {
233         return false;
234     }
235 
236     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_RECT_WIDTH, rect.width_)) {
237         return false;
238     }
239 
240     if (!ParseDimension(jsonSize, JsonTagConstants::JSON_RECT_HEIGHT, rect.height_)) {
241         return false;
242     }
243 
244     return true;
245 }
246 
FromJson(const nlohmann::json & jsonSrc)247 bool SecCompBase::FromJson(const nlohmann::json& jsonSrc)
248 {
249     SC_LOG_DEBUG(LABEL, "Button info %{public}s.", jsonSrc.dump().c_str());
250     if ((jsonSrc.find(JsonTagConstants::JSON_SC_TYPE) == jsonSrc.end()) ||
251         !jsonSrc.at(JsonTagConstants::JSON_SC_TYPE).is_number()) {
252         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", JsonTagConstants::JSON_SC_TYPE.c_str());
253         return false;
254     }
255     int32_t value = jsonSrc.at(JsonTagConstants::JSON_SC_TYPE).get<int32_t>();
256     if ((value <= static_cast<int32_t>(SecCompType::UNKNOWN_SC_TYPE)) ||
257         (value >= static_cast<int32_t>(SecCompType::MAX_SC_TYPE))) {
258         SC_LOG_ERROR(LABEL, "scType value is invalid.");
259         return false;
260     }
261     type_ = static_cast<SecCompType>(value);
262 
263     if ((jsonSrc.find(JsonTagConstants::JSON_NODE_ID) == jsonSrc.end()) ||
264         !jsonSrc.at(JsonTagConstants::JSON_NODE_ID).is_number()) {
265         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", JsonTagConstants::JSON_NODE_ID.c_str());
266         return false;
267     }
268     nodeId_ = jsonSrc.at(JsonTagConstants::JSON_NODE_ID).get<int32_t>();
269 
270     if (!ParseRect(jsonSrc, JsonTagConstants::JSON_RECT, rect_)) {
271         return false;
272     }
273     if (!ParseRect(jsonSrc, JsonTagConstants::JSON_WINDOW_RECT, windowRect_)) {
274         return false;
275     }
276     if (!ParseSize(jsonSrc, JsonTagConstants::JSON_SIZE_TAG)) {
277         return false;
278     }
279     if (!ParseColors(jsonSrc, JsonTagConstants::JSON_COLORS_TAG)) {
280         return false;
281     }
282     if (!ParseBorders(jsonSrc, JsonTagConstants::JSON_BORDER_TAG)) {
283         return false;
284     }
285     if (!ParseParent(jsonSrc, JsonTagConstants::JSON_PARENT_TAG)) {
286         return false;
287     }
288     if (!ParseStyle(jsonSrc, JsonTagConstants::JSON_STYLE_TAG)) {
289         return false;
290     }
291 
292     if ((jsonSrc.find(JsonTagConstants::JSON_WINDOW_ID) == jsonSrc.end()) ||
293         !jsonSrc.at(JsonTagConstants::JSON_WINDOW_ID).is_number()) {
294         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", JsonTagConstants::JSON_WINDOW_ID.c_str());
295         return false;
296     }
297     windowId_ = jsonSrc.at(JsonTagConstants::JSON_WINDOW_ID).get<int32_t>();
298     return true;
299 }
300 
ToJson(nlohmann::json & jsonRes) const301 void SecCompBase::ToJson(nlohmann::json& jsonRes) const
302 {
303     jsonRes[JsonTagConstants::JSON_SC_TYPE] = type_;
304     jsonRes[JsonTagConstants::JSON_NODE_ID] = nodeId_;
305     jsonRes[JsonTagConstants::JSON_RECT] = nlohmann::json {
306         {JsonTagConstants::JSON_RECT_X, rect_.x_},
307         {JsonTagConstants::JSON_RECT_Y, rect_.y_},
308         {JsonTagConstants::JSON_RECT_WIDTH, rect_.width_},
309         {JsonTagConstants::JSON_RECT_HEIGHT, rect_.height_}
310     };
311     jsonRes[JsonTagConstants::JSON_WINDOW_RECT] = nlohmann::json {
312         {JsonTagConstants::JSON_RECT_X, windowRect_.x_},
313         {JsonTagConstants::JSON_RECT_Y, windowRect_.y_},
314         {JsonTagConstants::JSON_RECT_WIDTH, windowRect_.width_},
315         {JsonTagConstants::JSON_RECT_HEIGHT, windowRect_.height_}
316     };
317     nlohmann::json jsonPadding = nlohmann::json {
318         { JsonTagConstants::JSON_PADDING_TOP_TAG, padding_.top },
319         { JsonTagConstants::JSON_PADDING_RIGHT_TAG, padding_.right },
320         { JsonTagConstants::JSON_PADDING_BOTTOM_TAG, padding_.bottom },
321         { JsonTagConstants::JSON_PADDING_LEFT_TAG, padding_.left },
322     };
323 
324     jsonRes[JsonTagConstants::JSON_SIZE_TAG] = nlohmann::json {
325         { JsonTagConstants::JSON_FONT_SIZE_TAG, fontSize_ },
326         { JsonTagConstants::JSON_ICON_SIZE_TAG, iconSize_ },
327         { JsonTagConstants::JSON_TEXT_ICON_PADDING_TAG, textIconSpace_ },
328         { JsonTagConstants::JSON_PADDING_SIZE_TAG, jsonPadding },
329     };
330 
331     jsonRes[JsonTagConstants::JSON_COLORS_TAG] = nlohmann::json {
332         { JsonTagConstants::JSON_FONT_COLOR_TAG, fontColor_.value },
333         { JsonTagConstants::JSON_ICON_COLOR_TAG, iconColor_.value },
334         { JsonTagConstants::JSON_BG_COLOR_TAG, bgColor_.value }
335     };
336 
337     jsonRes[JsonTagConstants::JSON_BORDER_TAG] = nlohmann::json {
338         { JsonTagConstants::JSON_BORDER_WIDTH_TAG, borderWidth_ },
339     };
340     jsonRes[JsonTagConstants::JSON_PARENT_TAG] = nlohmann::json {
341         { JsonTagConstants::JSON_PARENT_EFFECT_TAG, parentEffect_ },
342         { JsonTagConstants::JSON_IS_CLIPPED_TAG, isClipped_ },
343         { JsonTagConstants::JSON_TOP_CLIP_TAG, topClip_ },
344         { JsonTagConstants::JSON_BOTTOM_CLIP_TAG, bottomClip_ },
345         { JsonTagConstants::JSON_LEFT_CLIP_TAG, leftClip_ },
346         { JsonTagConstants::JSON_RIGHT_CLIP_TAG, rightClip_ },
347         { JsonTagConstants::JSON_PARENT_TAG_TAG, parentTag_ },
348     };
349 
350     jsonRes[JsonTagConstants::JSON_STYLE_TAG] = nlohmann::json {
351         { JsonTagConstants::JSON_TEXT_TAG, text_ },
352         { JsonTagConstants::JSON_ICON_TAG, icon_ },
353         { JsonTagConstants::JSON_BG_TAG, bg_ },
354     };
355     jsonRes[JsonTagConstants::JSON_WINDOW_ID] = windowId_;
356 }
357 
ToJsonStr() const358 std::string SecCompBase::ToJsonStr() const
359 {
360     nlohmann::json json;
361     ToJson(json);
362     return json.dump();
363 }
364 
CompareComponentBasicInfo(SecCompBase * other,bool isRectCheck) const365 bool SecCompBase::CompareComponentBasicInfo(SecCompBase *other, bool isRectCheck) const
366 {
367     if (other == nullptr) {
368         SC_LOG_ERROR(LABEL, "other is nullptr.");
369         return false;
370     }
371 
372     SecCompRect rect = other->rect_;
373     SecCompRect windowRect = other->windowRect_;
374     if (isRectCheck) {
375         rect = rect_;
376         windowRect = windowRect_;
377     }
378 
379     auto leftValue = std::tie(type_, fontSize_, iconSize_, textIconSpace_, padding_.top, padding_.right,
380         padding_.bottom, padding_.left, fontColor_.value, bgColor_.value, iconColor_.value, borderWidth_,
381         rect, windowRect);
382     auto rightValue = std::tie(other->type_, other->fontSize_, other->iconSize_, other->textIconSpace_,
383         other->padding_.top, other->padding_.right, other->padding_.bottom, other->padding_.left,
384         other->fontColor_.value, other->bgColor_.value, other->iconColor_.value, other->borderWidth_,
385         other->rect_, other->windowRect_);
386 
387     return (leftValue == rightValue);
388 }
389 
ParseStyle(const nlohmann::json & json,const std::string & tag)390 bool SecCompBase::ParseStyle(const nlohmann::json& json, const std::string& tag)
391 {
392     if ((json.find(tag) == json.end()) || !json.at(tag).is_object()) {
393         SC_LOG_ERROR(LABEL, "json: %{public}s tag invalid.", tag.c_str());
394         return false;
395     }
396     auto jsonStyle = json.at(tag);
397     if (jsonStyle.find(JsonTagConstants::JSON_TEXT_TAG) == jsonStyle.end() ||
398         !jsonStyle.at(JsonTagConstants::JSON_TEXT_TAG).is_number()) {
399         SC_LOG_ERROR(LABEL, "Json=%{public}s tag is invalid.", tag.c_str());
400         return false;
401     }
402     if (jsonStyle.find(JsonTagConstants::JSON_ICON_TAG) == jsonStyle.end() ||
403         !jsonStyle.at(JsonTagConstants::JSON_ICON_TAG).is_number()) {
404         SC_LOG_ERROR(LABEL, "Json=%{public}s tag is invalid.", tag.c_str());
405         return false;
406     }
407     if (jsonStyle.find(JsonTagConstants::JSON_BG_TAG) == jsonStyle.end() ||
408         !jsonStyle.at(JsonTagConstants::JSON_BG_TAG).is_number()) {
409         SC_LOG_ERROR(LABEL, "Json=%{public}s tag is invalid.", tag.c_str());
410         return false;
411     }
412     text_ = jsonStyle.at(JsonTagConstants::JSON_TEXT_TAG).get<int32_t>();
413     icon_ = jsonStyle.at(JsonTagConstants::JSON_ICON_TAG).get<int32_t>();
414     if (!IsTextIconTypeValid()) {
415         SC_LOG_ERROR(LABEL, "text or icon is invalid.");
416         return false;
417     }
418     bg_ = static_cast<SecCompBackground>(jsonStyle.at(JsonTagConstants::JSON_BG_TAG).get<int32_t>());
419     if ((bg_ <= SecCompBackground::UNKNOWN_BG) || (bg_ >= SecCompBackground::MAX_BG_TYPE)) {
420         SC_LOG_ERROR(LABEL, "bg is invalid.");
421         return false;
422     }
423     return true;
424 }
425 }  // namespace base
426 }  // namespace Security
427 }  // namespace OHOS
428