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 "distributed_preferences.h"
17 
18 #include <map>
19 
20 #include "ans_log_wrapper.h"
21 
22 namespace OHOS {
23 namespace Notification {
24 namespace {
25 const std::string DISTRIBUTED_LABEL = "distributed";
26 const std::string DELIMITER = "|";
27 const std::string MAIN_LABEL = "ans_main";
28 const std::string BUNDLE_LABEL = "bundle";
29 const std::string WITHOUT_APP = "without_app";
30 }  // namespace
31 
GetBoolFromString(const std::string & str)32 inline bool GetBoolFromString(const std::string &str)
33 {
34     return static_cast<bool>(atoi(str.data()));
35 }
36 
DistributedPreferences()37 DistributedPreferences::DistributedPreferences()
38 {
39     database_ = std::make_unique<DistributedPreferencesDatabase>();
40     preferencesInfo_ = std::make_unique<DistributedPreferencesInfo>();
41     InitDistributedAllInfo();
42 }
43 
~DistributedPreferences()44 DistributedPreferences::~DistributedPreferences()
45 {}
46 
InitDistributedAllInfo()47 bool DistributedPreferences::InitDistributedAllInfo()
48 {
49     std::vector<DistributedPreferencesDatabase::Entry> entries;
50     if (!database_->GetEntriesFromDistributedDB(DISTRIBUTED_LABEL, entries)) {
51         return false;
52     }
53 
54     for (auto entry : entries) {
55         if (!ResolveDistributedKey(entry)) {
56             ANS_LOGE("key <%{public}s> is invalid.", entry.key.ToString().c_str());
57         }
58     }
59 
60     return true;
61 }
62 
GetDistributedMainKey(std::string & key)63 void DistributedPreferences::GetDistributedMainKey(std::string &key)
64 {
65     key = DISTRIBUTED_LABEL + DELIMITER + MAIN_LABEL + DELIMITER;
66 }
67 
GetDistributedBundleKey(const sptr<NotificationBundleOption> & bundleOption,std::string & key)68 void DistributedPreferences::GetDistributedBundleKey(
69     const sptr<NotificationBundleOption> &bundleOption, std::string &key)
70 {
71     if (bundleOption) {
72         key = DISTRIBUTED_LABEL + DELIMITER + BUNDLE_LABEL + DELIMITER + bundleOption->GetBundleName() + DELIMITER +
73             std::to_string(bundleOption->GetUid());
74     }
75 }
76 
ResolveDistributedKey(const DistributedKv::Entry & entry)77 bool DistributedPreferences::ResolveDistributedKey(const DistributedKv::Entry &entry)
78 {
79     std::string key = entry.key.ToString();
80     std::size_t distributedLabelPosition = 0;
81     std::size_t distributedLabelEndPosition = key.find(DELIMITER, distributedLabelPosition);
82     if (distributedLabelEndPosition == std::string::npos) {
83         return false;
84     }
85     std::size_t typeLabelPosition = distributedLabelEndPosition + DELIMITER.size();
86     std::size_t typeLabelEndPosition = key.find(DELIMITER, typeLabelPosition);
87     if (typeLabelPosition == std::string::npos) {
88         return false;
89     }
90 
91     std::string sign = key.substr(typeLabelPosition, typeLabelEndPosition - typeLabelPosition);
92     if (sign == MAIN_LABEL) {
93         return ResolveDistributedEnable(entry.value.ToString());
94     }
95     if (sign == WITHOUT_APP) {
96         return ResolveSyncWithoutAppEnable(key, typeLabelEndPosition, entry.value.ToString());
97     }
98     return ResolveDistributedBundleEnable(key, typeLabelEndPosition, entry.value.ToString());
99 }
100 
ResolveDistributedEnable(const std::string & value)101 bool DistributedPreferences::ResolveDistributedEnable(const std::string &value)
102 {
103     int32_t enabled = atoi(value.data());
104     preferencesInfo_->SetDistributedEnable(static_cast<bool>(enabled));
105 
106     return true;
107 }
108 
ResolveDistributedBundleEnable(const std::string & key,const int32_t startPos,const std::string & value)109 bool DistributedPreferences::ResolveDistributedBundleEnable(const std::string &key,
110     const int32_t startPos, const std::string &value)
111 {
112     std::size_t bundleNamePosition = startPos + DELIMITER.size();
113     std::size_t bundleNameEndPosition = key.find(DELIMITER, bundleNamePosition);
114     if (bundleNameEndPosition == std::string::npos) {
115         return false;
116     }
117 
118     std::size_t uidPosition = key.find_last_of(DELIMITER) + DELIMITER.size();
119     if (uidPosition < bundleNameEndPosition) {
120         return false;
121     }
122 
123     std::string bundleName = key.substr(bundleNamePosition, bundleNameEndPosition - bundleNamePosition);
124     int32_t uid = atoi(&key[uidPosition]);
125     preferencesInfo_->SetDistributedBundleEnable(bundleName, uid, GetBoolFromString(value));
126 
127     return true;
128 }
129 
ResolveSyncWithoutAppEnable(const std::string & key,const int32_t startPos,const std::string & value)130 bool DistributedPreferences::ResolveSyncWithoutAppEnable(const std::string &key,
131     const int32_t startPos, const std::string &value)
132 {
133     std::size_t pos = startPos + DELIMITER.size();
134     int32_t userId = atoi(&key[pos]);
135     preferencesInfo_->SetSyncEnabledWithoutApp(userId, GetBoolFromString(value));
136 
137     return true;
138 }
139 
SetDistributedEnable(bool isEnable)140 ErrCode DistributedPreferences::SetDistributedEnable(bool isEnable)
141 {
142     ANS_LOGI("start");
143     std::string key;
144     GetDistributedMainKey(key);
145 
146     if (!database_->PutToDistributedDB(key, std::to_string(isEnable))) {
147         ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
148         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
149     }
150 
151     preferencesInfo_->SetDistributedEnable(isEnable);
152 
153     return ERR_OK;
154 }
155 
GetDistributedEnable(bool & isEnable)156 ErrCode DistributedPreferences::GetDistributedEnable(bool &isEnable)
157 {
158     ANS_LOGI("start");
159 
160     isEnable = preferencesInfo_->GetDistributedEnable();
161 
162     return ERR_OK;
163 }
164 
SetDistributedBundleEnable(const sptr<NotificationBundleOption> & bundleOption,bool isEnable)165 ErrCode DistributedPreferences::SetDistributedBundleEnable(
166     const sptr<NotificationBundleOption> &bundleOption, bool isEnable)
167 {
168     ANS_LOGI("start");
169     if (bundleOption == nullptr) {
170         ANS_LOGE("bundleOption is nullptr.");
171         return ERR_ANS_INVALID_PARAM;
172     }
173 
174     std::string key;
175     GetDistributedBundleKey(bundleOption, key);
176 
177     if (!database_->PutToDistributedDB(key, std::to_string(isEnable))) {
178         ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
179         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
180     }
181 
182     preferencesInfo_->SetDistributedBundleEnable(bundleOption->GetBundleName(), bundleOption->GetUid(), isEnable);
183 
184     return ERR_OK;
185 }
186 
GetDistributedBundleEnable(const sptr<NotificationBundleOption> & bundleOption,bool & isEnable)187 ErrCode DistributedPreferences::GetDistributedBundleEnable(
188     const sptr<NotificationBundleOption> &bundleOption, bool &isEnable)
189 {
190     if (bundleOption == nullptr) {
191         ANS_LOGE("bundleOption is nullptr.");
192         return ERR_ANS_INVALID_PARAM;
193     }
194 
195     if (preferencesInfo_ == nullptr) {
196         ANS_LOGE("preferencesInfo is nullptr");
197         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
198     }
199 
200     isEnable = preferencesInfo_->GetDistributedBundleEnable(bundleOption->GetBundleName(), bundleOption->GetUid());
201 
202     return ERR_OK;
203 }
204 
DeleteDistributedBundleInfo(const sptr<NotificationBundleOption> & bundleOption)205 ErrCode DistributedPreferences::DeleteDistributedBundleInfo(const sptr<NotificationBundleOption> &bundleOption)
206 {
207     if (bundleOption == nullptr) {
208         ANS_LOGE("bundleOption is nullptr.");
209         return ERR_ANS_INVALID_PARAM;
210     }
211 
212     if (database_ == nullptr || preferencesInfo_ == nullptr) {
213         ANS_LOGE("database or preferencesInfo is nullptr");
214         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
215     }
216 
217     std::string key;
218     GetDistributedBundleKey(bundleOption, key);
219 
220     if (!database_->DeleteToDistributedDB(key)) {
221         ANS_LOGE("delete to distributed DB failed. key:%{public}s", key.c_str());
222         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
223     }
224 
225     preferencesInfo_->DeleteDistributedBundleInfo(bundleOption->GetBundleName(), bundleOption->GetUid());
226 
227     return ERR_OK;
228 }
229 
ClearDataInRestoreFactorySettings()230 ErrCode DistributedPreferences::ClearDataInRestoreFactorySettings()
231 {
232     if (database_ == nullptr) {
233         ANS_LOGE("database is nullptr");
234         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
235     }
236 
237     if (!database_->ClearDatabase()) {
238         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
239     }
240 
241     SetDistributedEnable(false);
242 
243     preferencesInfo_ = std::make_unique<DistributedPreferencesInfo>();
244 
245     return ERR_OK;
246 }
247 
GetEnabledWithoutApp(const int32_t userId,std::string & key)248 void DistributedPreferences::GetEnabledWithoutApp(const int32_t userId, std::string &key)
249 {
250     key = DISTRIBUTED_LABEL + DELIMITER + WITHOUT_APP + DELIMITER + std::to_string(userId) + DELIMITER;
251 }
252 
SetSyncEnabledWithoutApp(const int32_t userId,const bool enabled)253 ErrCode DistributedPreferences::SetSyncEnabledWithoutApp(const int32_t userId, const bool enabled)
254 {
255     if (database_ == nullptr || preferencesInfo_ == nullptr) {
256         ANS_LOGE("database or preferencesInfo is nullptr");
257         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
258     }
259     std::string key;
260     GetEnabledWithoutApp(userId, key);
261     if (!database_->PutToDistributedDB(key, std::to_string(enabled))) {
262         ANS_LOGE("put to distributed DB failed. key:%{public}s", key.c_str());
263         return ERR_ANS_DISTRIBUTED_OPERATION_FAILED;
264     }
265     preferencesInfo_->SetSyncEnabledWithoutApp(userId, enabled);
266     return ERR_OK;
267 }
268 
GetSyncEnabledWithoutApp(const int32_t userId,bool & enabled)269 ErrCode DistributedPreferences::GetSyncEnabledWithoutApp(const int32_t userId, bool &enabled)
270 {
271     return preferencesInfo_ == nullptr ?
272         ERR_ANS_DISTRIBUTED_OPERATION_FAILED : preferencesInfo_->GetSyncEnabledWithoutApp(userId, enabled);
273 }
274 }  // namespace Notification
275 }  // namespace OHOS