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 <set>
18 #include "json_util.h"
19 #include "nlohmann/json.hpp"
20 #include "extension_form_profile.h"
21
22 namespace OHOS {
23 namespace AppExecFwk {
24 namespace {
25 thread_local int32_t parseResult;
26
27 const int32_t MAX_FORM_NAME = 127;
28 const std::map<std::string, FormsColorMode> formColorModeMap = {
29 {"auto", FormsColorMode::AUTO_MODE},
30 {"dark", FormsColorMode::DARK_MODE},
31 {"light", FormsColorMode::LIGHT_MODE}
32 };
33 const std::map<std::string, int32_t> dimensionMap = {
34 {"1*2", 1},
35 {"2*2", 2},
36 {"2*4", 3},
37 {"4*4", 4},
38 {"2*1", 5}
39 };
40 const std::map<std::string, FormType> formTypeMap = {
41 {"JS", FormType::JS},
42 {"eTS", FormType::ETS}
43 };
44
45 const std::map<std::string, FormType> uiSyntaxMap = {
46 {"hml", FormType::JS},
47 {"arkts", FormType::ETS}
48 };
49
50 struct Window {
51 int32_t designWidth = 720;
52 bool autoDesignWidth = false;
53 };
54
55 struct Metadata {
56 std::string name;
57 std::string value;
58 };
59
60 struct ExtensionFormProfileInfo {
61 std::string name;
62 std::string description;
63 std::string src;
64 Window window;
65 std::string colorMode = "auto";
66 std::string formConfigAbility;
67 std::string type = "JS";
68 std::string uiSyntax = "hml";
69 bool formVisibleNotify = false;
70 bool isDefault = false;
71 bool updateEnabled = false;
72 std::string scheduledUpdateTime = "";
73 int32_t updateDuration = 0;
74 std::string defaultDimension;
75 std::vector<std::string> supportDimensions {};
76 std::vector<Metadata> metadata {};
77 };
78
79 struct ExtensionFormProfileInfoVec {
80 std::vector<ExtensionFormProfileInfo> forms {};
81 };
82
from_json(const nlohmann::json & jsonObject,Metadata & metadata)83 void from_json(const nlohmann::json &jsonObject, Metadata &metadata)
84 {
85 const auto &jsonObjectEnd = jsonObject.end();
86 GetValueIfFindKey<std::string>(jsonObject,
87 jsonObjectEnd,
88 ExtensionFormProfileReader::METADATA_NAME,
89 metadata.name,
90 JsonType::STRING,
91 false,
92 parseResult,
93 ArrayType::NOT_ARRAY);
94 GetValueIfFindKey<std::string>(jsonObject,
95 jsonObjectEnd,
96 ExtensionFormProfileReader::METADATA_VALUE,
97 metadata.value,
98 JsonType::STRING,
99 false,
100 parseResult,
101 ArrayType::NOT_ARRAY);
102 }
103
from_json(const nlohmann::json & jsonObject,Window & window)104 void from_json(const nlohmann::json &jsonObject, Window &window)
105 {
106 const auto &jsonObjectEnd = jsonObject.end();
107 GetValueIfFindKey<int32_t>(jsonObject,
108 jsonObjectEnd,
109 ExtensionFormProfileReader::WINDOW_DESIGN_WIDTH,
110 window.designWidth,
111 JsonType::NUMBER,
112 false,
113 parseResult,
114 ArrayType::NOT_ARRAY);
115 GetValueIfFindKey<bool>(jsonObject,
116 jsonObjectEnd,
117 ExtensionFormProfileReader::WINDOW_AUTO_DESIGN_WIDTH,
118 window.autoDesignWidth,
119 JsonType::BOOLEAN,
120 false,
121 parseResult,
122 ArrayType::NOT_ARRAY);
123 }
124
from_json(const nlohmann::json & jsonObject,ExtensionFormProfileInfo & extensionFormProfileInfo)125 void from_json(const nlohmann::json &jsonObject, ExtensionFormProfileInfo &extensionFormProfileInfo)
126 {
127 const auto &jsonObjectEnd = jsonObject.end();
128 GetValueIfFindKey<std::string>(jsonObject,
129 jsonObjectEnd,
130 ExtensionFormProfileReader::NAME,
131 extensionFormProfileInfo.name,
132 JsonType::STRING,
133 true,
134 parseResult,
135 ArrayType::NOT_ARRAY);
136 GetValueIfFindKey<std::string>(jsonObject,
137 jsonObjectEnd,
138 ExtensionFormProfileReader::DESCRIPTION,
139 extensionFormProfileInfo.description,
140 JsonType::STRING,
141 false,
142 parseResult,
143 ArrayType::NOT_ARRAY);
144 GetValueIfFindKey<std::string>(jsonObject,
145 jsonObjectEnd,
146 ExtensionFormProfileReader::SRC,
147 extensionFormProfileInfo.src,
148 JsonType::STRING,
149 false,
150 parseResult,
151 ArrayType::NOT_ARRAY);
152 GetValueIfFindKey<Window>(jsonObject,
153 jsonObjectEnd,
154 ExtensionFormProfileReader::WINDOW,
155 extensionFormProfileInfo.window,
156 JsonType::OBJECT,
157 false,
158 parseResult,
159 ArrayType::NOT_ARRAY);
160 GetValueIfFindKey<std::string>(jsonObject,
161 jsonObjectEnd,
162 ExtensionFormProfileReader::COLOR_MODE,
163 extensionFormProfileInfo.colorMode,
164 JsonType::STRING,
165 false,
166 parseResult,
167 ArrayType::NOT_ARRAY);
168 GetValueIfFindKey<std::string>(jsonObject,
169 jsonObjectEnd,
170 ExtensionFormProfileReader::FORM_CONFIG_ABILITY,
171 extensionFormProfileInfo.formConfigAbility,
172 JsonType::STRING,
173 false,
174 parseResult,
175 ArrayType::NOT_ARRAY);
176 GetValueIfFindKey<std::string>(jsonObject,
177 jsonObjectEnd,
178 ExtensionFormProfileReader::TYPE,
179 extensionFormProfileInfo.type,
180 JsonType::STRING,
181 false,
182 parseResult,
183 ArrayType::NOT_ARRAY);
184 GetValueIfFindKey<std::string>(jsonObject,
185 jsonObjectEnd,
186 ExtensionFormProfileReader::UI_SYNTAX,
187 extensionFormProfileInfo.uiSyntax,
188 JsonType::STRING,
189 false,
190 parseResult,
191 ArrayType::NOT_ARRAY);
192 GetValueIfFindKey<bool>(jsonObject,
193 jsonObjectEnd,
194 ExtensionFormProfileReader::FORM_VISIBLE_NOTIFY,
195 extensionFormProfileInfo.formVisibleNotify,
196 JsonType::BOOLEAN,
197 false,
198 parseResult,
199 ArrayType::NOT_ARRAY);
200 GetValueIfFindKey<bool>(jsonObject,
201 jsonObjectEnd,
202 ExtensionFormProfileReader::IS_DEFAULT,
203 extensionFormProfileInfo.isDefault,
204 JsonType::BOOLEAN,
205 true,
206 parseResult,
207 ArrayType::NOT_ARRAY);
208 GetValueIfFindKey<bool>(jsonObject,
209 jsonObjectEnd,
210 ExtensionFormProfileReader::UPDATE_ENABLED,
211 extensionFormProfileInfo.updateEnabled,
212 JsonType::BOOLEAN,
213 true,
214 parseResult,
215 ArrayType::NOT_ARRAY);
216 GetValueIfFindKey<std::string>(jsonObject,
217 jsonObjectEnd,
218 ExtensionFormProfileReader::SCHEDULED_UPDATE_TIME,
219 extensionFormProfileInfo.scheduledUpdateTime,
220 JsonType::STRING,
221 false,
222 parseResult,
223 ArrayType::NOT_ARRAY);
224 GetValueIfFindKey<int32_t>(jsonObject,
225 jsonObjectEnd,
226 ExtensionFormProfileReader::UPDATE_DURATION,
227 extensionFormProfileInfo.updateDuration,
228 JsonType::NUMBER,
229 false,
230 parseResult,
231 ArrayType::NOT_ARRAY);
232 GetValueIfFindKey<std::string>(jsonObject,
233 jsonObjectEnd,
234 ExtensionFormProfileReader::DEFAULT_DIMENSION,
235 extensionFormProfileInfo.defaultDimension,
236 JsonType::STRING,
237 true,
238 parseResult,
239 ArrayType::NOT_ARRAY);
240 GetValueIfFindKey<std::vector<std::string>>(jsonObject,
241 jsonObjectEnd,
242 ExtensionFormProfileReader::SUPPORT_DIMENSIONS,
243 extensionFormProfileInfo.supportDimensions,
244 JsonType::ARRAY,
245 true,
246 parseResult,
247 ArrayType::STRING);
248 GetValueIfFindKey<std::vector<Metadata>>(jsonObject,
249 jsonObjectEnd,
250 ExtensionFormProfileReader::METADATA,
251 extensionFormProfileInfo.metadata,
252 JsonType::ARRAY,
253 false,
254 parseResult,
255 ArrayType::OBJECT);
256 }
257
from_json(const nlohmann::json & jsonObject,ExtensionFormProfileInfoVec & infos)258 void from_json(const nlohmann::json &jsonObject, ExtensionFormProfileInfoVec &infos)
259 {
260 const auto &jsonObjectEnd = jsonObject.end();
261 GetValueIfFindKey<std::vector<ExtensionFormProfileInfo>>(jsonObject,
262 jsonObjectEnd,
263 ExtensionFormProfileReader::FORMS,
264 infos.forms,
265 JsonType::ARRAY,
266 false,
267 parseResult,
268 ArrayType::OBJECT);
269 }
270
CheckFormNameIsValid(const std::string & name)271 bool CheckFormNameIsValid(const std::string &name)
272 {
273 if (name.empty()) {
274 return false;
275 }
276 if (name.size() > MAX_FORM_NAME) {
277 return false;
278 }
279 return true;
280 }
281
GetMetadata(const ExtensionFormProfileInfo & form,ExtensionFormInfo & info)282 bool GetMetadata(const ExtensionFormProfileInfo &form, ExtensionFormInfo &info)
283 {
284 std::set<int32_t> supportDimensionSet {};
285 for (const auto &dimension: form.supportDimensions) {
286 auto dimensionRes = std::find_if(std::begin(dimensionMap),
287 std::end(dimensionMap),
288 [&dimension](const auto &item) { return item.first == dimension; });
289 if (dimensionRes == dimensionMap.end()) {
290 APP_LOGW("dimension is invalid, form name is %{public}s", form.name.c_str());
291 continue;
292 }
293 supportDimensionSet.emplace(dimensionRes->second);
294 }
295
296 auto dimensionRes = std::find_if(std::begin(dimensionMap),
297 std::end(dimensionMap),
298 [&form](const auto &item) { return item.first == form.defaultDimension; });
299 if (dimensionRes == dimensionMap.end()) {
300 APP_LOGW("defaultDimension is invalid, form name is %{public}s", form.name.c_str());
301 return false;
302 }
303 if (supportDimensionSet.find(dimensionRes->second) == supportDimensionSet.end()) {
304 APP_LOGW("defaultDimension is not in supportDimensions, form name is %{public}s", form.name.c_str());
305 return false;
306 }
307
308 info.defaultDimension = dimensionRes->second;
309 for (const auto &dimension: supportDimensionSet) {
310 info.supportDimensions.emplace_back(dimension);
311 }
312 return true;
313 }
314
TransformToExtensionFormInfo(const ExtensionFormProfileInfo & form,ExtensionFormInfo & info)315 bool TransformToExtensionFormInfo(const ExtensionFormProfileInfo &form, ExtensionFormInfo &info)
316 {
317 if (!CheckFormNameIsValid(form.name)) {
318 APP_LOGE("form name is invalid");
319 return false;
320 }
321 info.name = form.name;
322 info.description = form.description;
323 info.src = form.src;
324 info.window.autoDesignWidth = form.window.autoDesignWidth;
325 info.window.designWidth = form.window.designWidth;
326
327 auto colorMode = std::find_if(std::begin(formColorModeMap),
328 std::end(formColorModeMap),
329 [&form](const auto &item) { return item.first == form.colorMode; });
330 if (colorMode != formColorModeMap.end()) {
331 info.colorMode = colorMode->second;
332 }
333
334 auto formType = formTypeMap.find(form.type);
335 if (formType != formTypeMap.end()) {
336 info.type = formType->second;
337 }
338
339 auto uiSyntaxType = uiSyntaxMap.find(form.uiSyntax);
340 if (uiSyntaxType != uiSyntaxMap.end()) {
341 info.uiSyntax = uiSyntaxType->second;
342 }
343
344 info.formConfigAbility = form.formConfigAbility;
345 info.formVisibleNotify = form.formVisibleNotify;
346 info.isDefault = form.isDefault;
347 info.updateEnabled = form.updateEnabled;
348 info.scheduledUpdateTime = form.scheduledUpdateTime;
349 info.updateDuration = form.updateDuration;
350
351 if (!GetMetadata(form, info)) {
352 return false;
353 }
354 for (const auto &data: form.metadata) {
355 FormCustomizeData customizeData;
356 customizeData.name = data.name;
357 customizeData.value = data.value;
358 info.metadata.emplace_back(customizeData);
359 }
360 return true;
361 }
362
TransformToInfos(const ExtensionFormProfileInfoVec & forms,std::vector<ExtensionFormInfo> & infos)363 bool TransformToInfos(const ExtensionFormProfileInfoVec &forms, std::vector<ExtensionFormInfo> &infos)
364 {
365 APP_LOGI("transform ExtensionFormProfileInfo to ExtensionFormInfo");
366 for (const auto &form: forms.forms) {
367 ExtensionFormInfo info;
368 if (!TransformToExtensionFormInfo(form, info)) {
369 return false;
370 }
371 infos.push_back(info);
372 }
373 return true;
374 }
375 } // namespace
376
TransformTo(const std::string & formProfile,std::vector<ExtensionFormInfo> & infos)377 ErrCode ExtensionFormProfile::TransformTo(const std::string &formProfile, std::vector<ExtensionFormInfo> &infos)
378 {
379 APP_LOGI("transform profile to extension form infos");
380 nlohmann::json jsonObject = nlohmann::json::parse(formProfile, nullptr, false);
381 if (jsonObject.is_discarded()) {
382 APP_LOGE("bad profile");
383 return ERR_APPEXECFWK_PARSE_BAD_PROFILE;
384 }
385
386 auto forms = jsonObject.get<ExtensionFormProfileInfoVec>();
387 if (parseResult != ERR_OK) {
388 APP_LOGE("parseResult is %{public}d", parseResult);
389 int32_t ret = parseResult;
390 // need recover parse result to ERR_OK
391 parseResult = ERR_OK;
392 return ret;
393 }
394
395 if (!TransformToInfos(forms, infos)) {
396 return ERR_APPEXECFWK_PARSE_PROFILE_PROP_CHECK_ERROR;
397 }
398 return ERR_OK;
399 }
400 } // namespace AppExecFwk
401 } // namespace OHOS
402