1 /*
2  * Copyright (c) 2022 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 "bundle_user_info.h"
17 
18 #include <cerrno>
19 #include <cstring>
20 #include <fcntl.h>
21 #include <unistd.h>
22 
23 #include "json_util.h"
24 #include "nlohmann/json.hpp"
25 #include "parcel_macro.h"
26 #include "string_ex.h"
27 
28 namespace OHOS {
29 namespace AppExecFwk {
30 namespace {
31 const char* BUNDLE_USER_INFO_USER_ID = "userId";
32 const char* BUNDLE_USER_INFO_ENABLE = "enabled";
33 const char* BUNDLE_USER_INFO_DISABLE_ABILITIES = "disabledAbilities";
34 const char* BUNDLE_USER_INFO_OVERLAY_STATE = "overlayState";
35 const char* BUNDLE_USER_INFO_SET_ENABLED_CALLER = "setEnabledCaller";
36 } // namespace
37 
ReadFromParcel(Parcel & parcel)38 bool BundleUserInfo::ReadFromParcel(Parcel &parcel)
39 {
40     userId = parcel.ReadInt32();
41     enabled = parcel.ReadBool();
42     int32_t disabledAbilitiesSize;
43     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, disabledAbilitiesSize);
44     CONTAINER_SECURITY_VERIFY(parcel, disabledAbilitiesSize, &disabledAbilities);
45     for (int32_t i = 0; i < disabledAbilitiesSize; i++) {
46         disabledAbilities.emplace_back(Str16ToStr8(parcel.ReadString16()));
47     }
48 
49     int32_t overlayStateSize;
50     READ_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, overlayStateSize);
51     CONTAINER_SECURITY_VERIFY(parcel, overlayStateSize, &overlayModulesState);
52     for (int32_t i = 0; i < overlayStateSize; i++) {
53         overlayModulesState.emplace_back(Str16ToStr8(parcel.ReadString16()));
54     }
55     setEnabledCaller = Str16ToStr8(parcel.ReadString16());
56     return true;
57 }
58 
Unmarshalling(Parcel & parcel)59 BundleUserInfo *BundleUserInfo::Unmarshalling(Parcel &parcel)
60 {
61     BundleUserInfo *info = new (std::nothrow) BundleUserInfo();
62     if (info && !info->ReadFromParcel(parcel)) {
63         APP_LOGW("read from parcel failed");
64         delete info;
65         info = nullptr;
66     }
67 
68     return info;
69 }
70 
Marshalling(Parcel & parcel) const71 bool BundleUserInfo::Marshalling(Parcel &parcel) const
72 {
73     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, userId);
74     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Bool, parcel, enabled);
75     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, disabledAbilities.size());
76     for (auto &disabledAbility : disabledAbilities) {
77         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(disabledAbility));
78     }
79     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(Int32, parcel, overlayModulesState.size());
80     for (const auto &overlayModuleState : overlayModulesState) {
81         WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(overlayModuleState));
82     }
83     WRITE_PARCEL_AND_RETURN_FALSE_IF_FAIL(String16, parcel, Str8ToStr16(setEnabledCaller));
84     return true;
85 }
86 
Dump(const std::string & prefix,int fd)87 void BundleUserInfo::Dump(const std::string &prefix, int fd)
88 {
89     APP_LOGI("called dump BundleUserInfo");
90     if (fd < 0) {
91         APP_LOGE("dump BundleUserInfo fd error");
92         return;
93     }
94     int flags = fcntl(fd, F_GETFL);
95     if (flags < 0) {
96         APP_LOGE("BundleUserInfo fcntl error %{public}s", strerror(errno));
97         return;
98     }
99     uint uflags = static_cast<uint>(flags);
100     uflags &= O_ACCMODE;
101     if ((uflags == O_WRONLY) || (uflags == O_RDWR)) {
102         nlohmann::json jsonObject = *this;
103         std::string result;
104         result.append(prefix);
105         result.append(jsonObject.dump(Constants::DUMP_INDENT));
106         int ret = TEMP_FAILURE_RETRY(write(fd, result.c_str(), result.size()));
107         if (ret < 0) {
108             APP_LOGE("BundleUserInfo write error %{public}s", strerror(errno));
109         }
110     }
111 }
112 
IsInitialState() const113 bool BundleUserInfo::IsInitialState() const
114 {
115     return enabled && disabledAbilities.empty();
116 }
117 
Reset()118 void BundleUserInfo::Reset()
119 {
120     enabled = true;
121     disabledAbilities.clear();
122 }
123 
to_json(nlohmann::json & jsonObject,const BundleUserInfo & bundleUserInfo)124 void to_json(nlohmann::json& jsonObject, const BundleUserInfo& bundleUserInfo)
125 {
126     jsonObject = nlohmann::json {
127         {BUNDLE_USER_INFO_USER_ID, bundleUserInfo.userId},
128         {BUNDLE_USER_INFO_ENABLE, bundleUserInfo.enabled},
129         {BUNDLE_USER_INFO_DISABLE_ABILITIES, bundleUserInfo.disabledAbilities},
130         {BUNDLE_USER_INFO_OVERLAY_STATE, bundleUserInfo.overlayModulesState},
131         {BUNDLE_USER_INFO_SET_ENABLED_CALLER, bundleUserInfo.setEnabledCaller},
132     };
133 }
134 
from_json(const nlohmann::json & jsonObject,BundleUserInfo & bundleUserInfo)135 void from_json(const nlohmann::json& jsonObject, BundleUserInfo& bundleUserInfo)
136 {
137     const auto &jsonObjectEnd = jsonObject.end();
138     int32_t parseResult = ERR_OK;
139     GetValueIfFindKey<int32_t>(jsonObject,
140         jsonObjectEnd,
141         BUNDLE_USER_INFO_USER_ID,
142         bundleUserInfo.userId,
143         JsonType::NUMBER,
144         false,
145         parseResult,
146         ArrayType::NOT_ARRAY);
147     GetValueIfFindKey<bool>(jsonObject,
148         jsonObjectEnd,
149         BUNDLE_USER_INFO_ENABLE,
150         bundleUserInfo.enabled,
151         JsonType::BOOLEAN,
152         false,
153         parseResult,
154         ArrayType::NOT_ARRAY);
155     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
156         jsonObjectEnd,
157         BUNDLE_USER_INFO_DISABLE_ABILITIES,
158         bundleUserInfo.disabledAbilities,
159         JsonType::ARRAY,
160         false,
161         parseResult,
162         ArrayType::STRING);
163     GetValueIfFindKey<std::vector<std::string>>(jsonObject,
164         jsonObjectEnd,
165         BUNDLE_USER_INFO_OVERLAY_STATE,
166         bundleUserInfo.overlayModulesState,
167         JsonType::ARRAY,
168         false,
169         parseResult,
170         ArrayType::STRING);
171     GetValueIfFindKey<std::string>(jsonObject,
172         jsonObjectEnd,
173         BUNDLE_USER_INFO_SET_ENABLED_CALLER,
174         bundleUserInfo.setEnabledCaller,
175         JsonType::STRING,
176         false,
177         parseResult,
178         ArrayType::NOT_ARRAY);
179     if (parseResult != ERR_OK) {
180         APP_LOGE("module bundleUserInfo jsonObject error : %{public}d", parseResult);
181     }
182 }
183 } // namespace AppExecFwk
184 } // namespace OHOS