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