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 
16 #include <map>
17 #include <mutex>
18 #include <set>
19 
20 #include"extension_form_profile.h"
21 #include "json_util.h"
22 #include "nlohmann/json.hpp"
23 
24 namespace OHOS {
25 namespace AppExecFwk {
26 namespace {
27 int32_t g_parseResult = ERR_OK;
28 std::mutex g_mutex;
29 
30 const int8_t MAX_FORM_NAME = 127;
31 const int8_t DEFAULT_RECT_SHAPE = 1;
32 const std::map<std::string, FormsColorMode> formColorModeMap = {
33     {"auto",  FormsColorMode::AUTO_MODE},
34     {"dark",  FormsColorMode::DARK_MODE},
35     {"light", FormsColorMode::LIGHT_MODE}
36 };
37 const std::map<std::string, int32_t> dimensionMap = {
38     {"1*2", 1},
39     {"2*2", 2},
40     {"2*4", 3},
41     {"4*4", 4},
42     {"2*1", 5},
43     {"1*1", 6},
44     {"6*4", 7}
45 };
46 const std::map<std::string, int32_t> shapeMap = {
47     {"rect", 1},
48     {"circle", 2}
49 };
50 const std::map<std::string, FormType> formTypeMap = {
51     {"JS", FormType::JS},
52     {"eTS", FormType::ETS}
53 };
54 
55 const std::map<std::string, FormType> uiSyntaxMap = {
56     {"hml", FormType::JS},
57     {"arkts", FormType::ETS}
58 };
59 
60 struct Window {
61     int32_t designWidth = 720;
62     bool autoDesignWidth = false;
63 };
64 
65 struct Metadata {
66     std::string name;
67     std::string value;
68 };
69 
70 struct ExtensionFormProfileInfo {
71     std::string name;
72     std::string displayName;
73     std::string description;
74     std::string src;
75     Window window;
76     std::string colorMode = "auto";
77     std::string formConfigAbility;
78     std::string type = "JS";
79     std::string uiSyntax = "hml";
80     std::string scheduledUpdateTime = "";
81     int32_t updateDuration = 0;
82     std::string defaultDimension;
83     bool formVisibleNotify = false;
84     bool isDefault = false;
85     bool updateEnabled = false;
86     bool dataProxyEnabled = false;
87     bool isDynamic = true;
88     bool transparencyEnabled = false;
89     bool fontScaleFollowSystem = true;
90     std::vector<std::string> supportShapes {};
91     std::vector<std::string> supportDimensions {};
92     std::vector<Metadata> metadata {};
93 };
94 
95 struct ExtensionFormProfileInfoStruct {
96     int32_t privacyLevel = 0;
97     std::vector<ExtensionFormProfileInfo> forms {};
98 };
99 
from_json(const nlohmann::json & jsonObject,Metadata & metadata)100 void from_json(const nlohmann::json &jsonObject, Metadata &metadata)
101 {
102     const auto &jsonObjectEnd = jsonObject.end();
103     GetValueIfFindKey<std::string>(jsonObject,
104         jsonObjectEnd,
105         ExtensionFormProfileReader::METADATA_NAME,
106         metadata.name,
107         JsonType::STRING,
108         false,
109         g_parseResult,
110         ArrayType::NOT_ARRAY);
111     GetValueIfFindKey<std::string>(jsonObject,
112         jsonObjectEnd,
113         ExtensionFormProfileReader::METADATA_VALUE,
114         metadata.value,
115         JsonType::STRING,
116         false,
117         g_parseResult,
118         ArrayType::NOT_ARRAY);
119 }
120 
from_json(const nlohmann::json & jsonObject,Window & window)121 void from_json(const nlohmann::json &jsonObject, Window &window)
122 {
123     const auto &jsonObjectEnd = jsonObject.end();
124     GetValueIfFindKey<int32_t>(jsonObject,
125         jsonObjectEnd,
126         ExtensionFormProfileReader::WINDOW_DESIGN_WIDTH,
127         window.designWidth,
128         JsonType::NUMBER,
129         false,
130         g_parseResult,
131         ArrayType::NOT_ARRAY);
132     GetValueIfFindKey<bool>(jsonObject,
133         jsonObjectEnd,
134         ExtensionFormProfileReader::WINDOW_AUTO_DESIGN_WIDTH,
135         window.autoDesignWidth,
136         JsonType::BOOLEAN,
137         false,
138         g_parseResult,
139         ArrayType::NOT_ARRAY);
140 }
141 
from_json(const nlohmann::json & jsonObject,ExtensionFormProfileInfo & extensionFormProfileInfo)142 void from_json(const nlohmann::json &jsonObject, ExtensionFormProfileInfo &extensionFormProfileInfo)
143 {
144     const auto &jsonObjectEnd = jsonObject.end();
145     GetValueIfFindKey<std::string>(jsonObject,
146         jsonObjectEnd,
147         ExtensionFormProfileReader::NAME,
148         extensionFormProfileInfo.name,
149         JsonType::STRING,
150         true,
151         g_parseResult,
152         ArrayType::NOT_ARRAY);
153     GetValueIfFindKey<std::string>(jsonObject,
154         jsonObjectEnd,
155         ExtensionFormProfileReader::DISPLAY_NAME,
156         extensionFormProfileInfo.displayName,
157         JsonType::STRING,
158         false,
159         g_parseResult,
160         ArrayType::NOT_ARRAY);
161     GetValueIfFindKey<std::string>(jsonObject,
162         jsonObjectEnd,
163         ExtensionFormProfileReader::DESCRIPTION,
164         extensionFormProfileInfo.description,
165         JsonType::STRING,
166         false,
167         g_parseResult,
168         ArrayType::NOT_ARRAY);
169     GetValueIfFindKey<std::string>(jsonObject,
170         jsonObjectEnd,
171         ExtensionFormProfileReader::SRC,
172         extensionFormProfileInfo.src,
173         JsonType::STRING,
174         false,
175         g_parseResult,
176         ArrayType::NOT_ARRAY);
177     GetValueIfFindKey<Window>(jsonObject,
178         jsonObjectEnd,
179         ExtensionFormProfileReader::WINDOW,
180         extensionFormProfileInfo.window,
181         JsonType::OBJECT,
182         false,
183         g_parseResult,
184         ArrayType::NOT_ARRAY);
185     GetValueIfFindKey<std::string>(jsonObject,
186         jsonObjectEnd,
187         ExtensionFormProfileReader::COLOR_MODE,
188         extensionFormProfileInfo.colorMode,
189         JsonType::STRING,
190         false,
191         g_parseResult,
192         ArrayType::NOT_ARRAY);
193     GetValueIfFindKey<std::string>(jsonObject,
194         jsonObjectEnd,
195         ExtensionFormProfileReader::FORM_CONFIG_ABILITY,
196         extensionFormProfileInfo.formConfigAbility,
197         JsonType::STRING,
198         false,
199         g_parseResult,
200         ArrayType::NOT_ARRAY);
201     GetValueIfFindKey<std::string>(jsonObject,
202         jsonObjectEnd,
203         ExtensionFormProfileReader::TYPE,
204         extensionFormProfileInfo.type,
205         JsonType::STRING,
206         false,
207         g_parseResult,
208         ArrayType::NOT_ARRAY);
209     GetValueIfFindKey<std::string>(jsonObject,
210         jsonObjectEnd,
211         ExtensionFormProfileReader::UI_SYNTAX,
212         extensionFormProfileInfo.uiSyntax,
213         JsonType::STRING,
214         false,
215         g_parseResult,
216         ArrayType::NOT_ARRAY);
217     GetValueIfFindKey<bool>(jsonObject,
218         jsonObjectEnd,
219         ExtensionFormProfileReader::FORM_VISIBLE_NOTIFY,
220         extensionFormProfileInfo.formVisibleNotify,
221         JsonType::BOOLEAN,
222         false,
223         g_parseResult,
224         ArrayType::NOT_ARRAY);
225     GetValueIfFindKey<bool>(jsonObject,
226         jsonObjectEnd,
227         ExtensionFormProfileReader::IS_DEFAULT,
228         extensionFormProfileInfo.isDefault,
229         JsonType::BOOLEAN,
230         true,
231         g_parseResult,
232         ArrayType::NOT_ARRAY);
233     GetValueIfFindKey<bool>(jsonObject,
234         jsonObjectEnd,
235         ExtensionFormProfileReader::UPDATE_ENABLED,
236         extensionFormProfileInfo.updateEnabled,
237         JsonType::BOOLEAN,
238         true,
239         g_parseResult,
240         ArrayType::NOT_ARRAY);
241     GetValueIfFindKey<std::string>(jsonObject,
242         jsonObjectEnd,
243         ExtensionFormProfileReader::SCHEDULED_UPDATE_TIME,
244         extensionFormProfileInfo.scheduledUpdateTime,
245         JsonType::STRING,
246         false,
247         g_parseResult,
248         ArrayType::NOT_ARRAY);
249     GetValueIfFindKey<int32_t>(jsonObject,
250         jsonObjectEnd,
251         ExtensionFormProfileReader::UPDATE_DURATION,
252         extensionFormProfileInfo.updateDuration,
253         JsonType::NUMBER,
254         false,
255         g_parseResult,
256         ArrayType::NOT_ARRAY);
257     GetValueIfFindKey<std::string>(jsonObject,
258         jsonObjectEnd,
259         ExtensionFormProfileReader::DEFAULT_DIMENSION,
260         extensionFormProfileInfo.defaultDimension,
261         JsonType::STRING,
262         true,
263         g_parseResult,
264         ArrayType::NOT_ARRAY);
265     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
266         jsonObjectEnd,
267         ExtensionFormProfileReader::SUPPORT_DIMENSIONS,
268         extensionFormProfileInfo.supportDimensions,
269         JsonType::ARRAY,
270         true,
271         g_parseResult,
272         ArrayType::STRING);
273     GetValueIfFindKey<std::vector<Metadata>>(jsonObject,
274         jsonObjectEnd,
275         ExtensionFormProfileReader::METADATA,
276         extensionFormProfileInfo.metadata,
277         JsonType::ARRAY,
278         false,
279         g_parseResult,
280         ArrayType::OBJECT);
281     GetValueIfFindKey<bool>(jsonObject,
282         jsonObjectEnd,
283         ExtensionFormProfileReader::DATA_PROXY_ENABLED,
284         extensionFormProfileInfo.dataProxyEnabled,
285         JsonType::BOOLEAN,
286         false,
287         g_parseResult,
288         ArrayType::NOT_ARRAY);
289     GetValueIfFindKey<bool>(jsonObject,
290         jsonObjectEnd,
291         ExtensionFormProfileReader::IS_DYNAMIC,
292         extensionFormProfileInfo.isDynamic,
293         JsonType::BOOLEAN,
294         false,
295         g_parseResult,
296         ArrayType::NOT_ARRAY);
297     GetValueIfFindKey<bool>(jsonObject,
298         jsonObjectEnd,
299         ExtensionFormProfileReader::TRANSPARENCY_ENABLED,
300         extensionFormProfileInfo.transparencyEnabled,
301         JsonType::BOOLEAN,
302         false,
303         g_parseResult,
304         ArrayType::NOT_ARRAY);
305     GetValueIfFindKey<bool>(jsonObject,
306         jsonObjectEnd,
307         ExtensionFormProfileReader::FONT_SCALE_FOLLOW_SYSTEM,
308         extensionFormProfileInfo.fontScaleFollowSystem,
309         JsonType::BOOLEAN,
310         false,
311         g_parseResult,
312         ArrayType::NOT_ARRAY);
313     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
314         jsonObjectEnd,
315         ExtensionFormProfileReader::SUPPORT_SHAPES,
316         extensionFormProfileInfo.supportShapes,
317         JsonType::ARRAY,
318         false,
319         g_parseResult,
320         ArrayType::STRING);
321 }
322 
from_json(const nlohmann::json & jsonObject,ExtensionFormProfileInfoStruct & profileInfo)323 void from_json(const nlohmann::json &jsonObject, ExtensionFormProfileInfoStruct &profileInfo)
324 {
325     const auto &jsonObjectEnd = jsonObject.end();
326     GetValueIfFindKey<int32_t>(jsonObject,
327         jsonObjectEnd,
328         ExtensionFormProfileReader::PRIVACY_LEVEL,
329         profileInfo.privacyLevel,
330         JsonType::NUMBER,
331         false,
332         g_parseResult,
333         ArrayType::NOT_ARRAY);
334     GetValueIfFindKey<std::vector<ExtensionFormProfileInfo>>(jsonObject,
335         jsonObjectEnd,
336         ExtensionFormProfileReader::FORMS,
337         profileInfo.forms,
338         JsonType::ARRAY,
339         false,
340         g_parseResult,
341         ArrayType::OBJECT);
342 }
343 
CheckFormNameIsValid(const std::string & name)344 bool CheckFormNameIsValid(const std::string &name)
345 {
346     if (name.empty()) {
347         APP_LOGE("name is empty");
348         return false;
349     }
350     if (name.size() > MAX_FORM_NAME) {
351         APP_LOGE("name size is too long");
352         return false;
353     }
354     return true;
355 }
356 
GetMetadata(const ExtensionFormProfileInfo & form,ExtensionFormInfo & info)357 bool GetMetadata(const ExtensionFormProfileInfo &form, ExtensionFormInfo &info)
358 {
359     std::set<int32_t> supportDimensionSet {};
360     for (const auto &dimension: form.supportDimensions) {
361         auto dimensionRes = std::find_if(std::begin(dimensionMap),
362             std::end(dimensionMap),
363             [&dimension](const auto &item) { return item.first == dimension; });
364         if (dimensionRes == dimensionMap.end()) {
365             APP_LOGW("dimension invalid form %{public}s", form.name.c_str());
366             continue;
367         }
368         supportDimensionSet.emplace(dimensionRes->second);
369     }
370 
371     auto dimensionRes = std::find_if(std::begin(dimensionMap),
372         std::end(dimensionMap),
373         [&form](const auto &item) { return item.first == form.defaultDimension; });
374     if (dimensionRes == dimensionMap.end()) {
375         APP_LOGW("defaultDimension invalid form %{public}s", form.name.c_str());
376         return false;
377     }
378     if (supportDimensionSet.find(dimensionRes->second) == supportDimensionSet.end()) {
379         APP_LOGW("defaultDimension not in supportDimensions form %{public}s", form.name.c_str());
380         return false;
381     }
382 
383     info.defaultDimension = dimensionRes->second;
384     for (const auto &dimension: supportDimensionSet) {
385         info.supportDimensions.emplace_back(dimension);
386     }
387     return true;
388 }
389 
GetSupportShapes(const ExtensionFormProfileInfo & form,ExtensionFormInfo & info)390 bool GetSupportShapes(const ExtensionFormProfileInfo &form, ExtensionFormInfo &info)
391 {
392     std::set<int32_t> supportShapeSet {};
393     for (const auto &shape: form.supportShapes) {
394         auto formShape = std::find_if(std::begin(shapeMap), std::end(shapeMap),
395             [&shape](const auto &item) { return item.first == shape; });
396         if (formShape == shapeMap.end()) {
397             APP_LOGW("shape invalid form %{public}s", form.name.c_str());
398             continue;
399         }
400         supportShapeSet.emplace(formShape->second);
401     }
402 
403     if (supportShapeSet.empty()) {
404         supportShapeSet.emplace(DEFAULT_RECT_SHAPE);
405     }
406 
407     for (const auto &shape: supportShapeSet) {
408         info.supportShapes.emplace_back(shape);
409     }
410     return true;
411 }
412 
TransformToExtensionFormInfo(const ExtensionFormProfileInfo & form,ExtensionFormInfo & info)413 bool TransformToExtensionFormInfo(const ExtensionFormProfileInfo &form, ExtensionFormInfo &info)
414 {
415     if (!CheckFormNameIsValid(form.name)) {
416         APP_LOGE("form name is invalid");
417         return false;
418     }
419     info.name = form.name;
420     info.description = form.description;
421     info.displayName = form.displayName;
422     info.src = form.src;
423     info.window.autoDesignWidth = form.window.autoDesignWidth;
424     info.window.designWidth = form.window.designWidth;
425 
426     auto colorMode = std::find_if(std::begin(formColorModeMap),
427         std::end(formColorModeMap),
428         [&form](const auto &item) { return item.first == form.colorMode; });
429     if (colorMode != formColorModeMap.end()) {
430         info.colorMode = colorMode->second;
431     }
432 
433     auto formType = formTypeMap.find(form.type);
434     if (formType != formTypeMap.end()) {
435         info.type = formType->second;
436     }
437 
438     auto uiSyntaxType = uiSyntaxMap.find(form.uiSyntax);
439     if (uiSyntaxType != uiSyntaxMap.end()) {
440         info.uiSyntax = uiSyntaxType->second;
441     }
442 
443     info.formConfigAbility = form.formConfigAbility;
444     info.formVisibleNotify = form.formVisibleNotify;
445     info.isDefault = form.isDefault;
446     info.updateEnabled = form.updateEnabled;
447     info.scheduledUpdateTime = form.scheduledUpdateTime;
448     info.updateDuration = form.updateDuration;
449 
450     if (!GetMetadata(form, info)) {
451         return false;
452     }
453     for (const auto &data: form.metadata) {
454         FormCustomizeData customizeData;
455         customizeData.name = data.name;
456         customizeData.value = data.value;
457         info.metadata.emplace_back(customizeData);
458     }
459 
460     info.dataProxyEnabled = form.dataProxyEnabled;
461     info.isDynamic = form.isDynamic;
462     info.transparencyEnabled = form.transparencyEnabled;
463     info.fontScaleFollowSystem = form.fontScaleFollowSystem;
464 
465     if (!GetSupportShapes(form, info)) {
466         return false;
467     }
468     return true;
469 }
470 
TransformToInfos(const ExtensionFormProfileInfoStruct & profileInfo,std::vector<ExtensionFormInfo> & infos)471 bool TransformToInfos(const ExtensionFormProfileInfoStruct &profileInfo, std::vector<ExtensionFormInfo> &infos)
472 {
473     APP_LOGD("transform ExtensionFormProfileInfo to ExtensionFormInfo");
474     for (const auto &form: profileInfo.forms) {
475         ExtensionFormInfo info;
476         if (!TransformToExtensionFormInfo(form, info)) {
477             return false;
478         }
479         infos.push_back(info);
480     }
481     return true;
482 }
483 } // namespace
484 
TransformTo(const std::string & formProfile,std::vector<ExtensionFormInfo> & infos,int32_t & privacyLevel)485 ErrCode ExtensionFormProfile::TransformTo(
486     const std::string &formProfile, std::vector<ExtensionFormInfo> &infos, int32_t &privacyLevel)
487 {
488     APP_LOGD("transform profile to extension form infos");
489     nlohmann::json jsonObject = nlohmann::json::parse(formProfile, nullptr, false);
490     if (jsonObject.is_discarded()) {
491         APP_LOGE("bad profile");
492         return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
493     }
494 
495     ExtensionFormProfileInfoStruct profileInfo;
496     {
497         std::lock_guard<std::mutex> lock(g_mutex);
498         g_parseResult = ERR_OK;
499         profileInfo = jsonObject.get<ExtensionFormProfileInfoStruct>();
500         privacyLevel = profileInfo.privacyLevel;
501         if (g_parseResult != ERR_OK) {
502             APP_LOGE("g_parseResult %{public}d", g_parseResult);
503             int32_t ret = g_parseResult;
504             // need recover parse result to ERR_OK
505             g_parseResult = ERR_OK;
506             return ret;
507         }
508     }
509 
510     if (!TransformToInfos(profileInfo, infos)) {
511         return ERR_APPEXECFWK_PARSE_PROFILE_PROP_CHECK_ERROR;
512     }
513     return ERR_OK;
514 }
515 }  // namespace AppExecFwk
516 }  // namespace OHOS
517