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