1 /*
2 * Copyright (c) 2024 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 #include "prop_n_operation.h"
16
17 #include "b_error/b_error.h"
18 #include "b_incremental_data.h"
19 #include "b_resources/b_constants.h"
20 #include "b_sa/b_sa_utils.h"
21 #include "filemgmt_libhilog.h"
22 #include "filemgmt_libn.h"
23 #include "incremental_backup_data.h"
24 #include "service_proxy.h"
25 #include "access_token.h"
26 #include "accesstoken_kit.h"
27 #include "ipc_skeleton.h"
28 #include "tokenid_kit.h"
29
30 namespace OHOS::FileManagement::Backup {
31 using namespace std;
32 using namespace LibN;
33
AsyncCallback(napi_env env,const NFuncArg & funcArg)34 static napi_value AsyncCallback(napi_env env, const NFuncArg& funcArg)
35 {
36 HILOGD("called LocalCapabilities::AsyncCallback begin");
37
38 auto fd = make_shared<UniqueFd>();
39 auto cbExec = [fd]() -> NError {
40 HILOGI("called LocalCapabilities::AsyncCallback cbExec");
41 ServiceProxy::InvaildInstance();
42 auto proxy = ServiceProxy::GetInstance();
43 if (!proxy) {
44 HILOGI("called LocalCapabilities::AsyncCallback cbExec, failed to get proxy");
45 return NError(errno);
46 }
47 *fd = proxy->GetLocalCapabilities();
48 HILOGI("called LocalCapabilities::AsyncCallback cbExec success");
49 return NError(ERRNO_NOERR);
50 };
51 auto cbCompl = [fd](napi_env env, NError err) -> NVal {
52 HILOGI("called LocalCapabilities::AsyncCallback cbCompl");
53 if (err) {
54 return {env, err.GetNapiErr(env)};
55 }
56 NVal obj = NVal::CreateObject(env);
57 obj.AddProp({NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_)});
58 return {obj};
59 };
60
61 NVal thisVar(env, funcArg.GetThisVar());
62 if (funcArg.GetArgc() == NARG_CNT::ZERO) {
63 HILOGI("called LocalCapabilities::Async::promise");
64 return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_LOCALCAPABILITIES_NAME, cbExec, cbCompl).val_;
65 } else {
66 HILOGI("called LocalCapabilities::Async::callback");
67 NVal cb(env, funcArg[NARG_POS::FIRST]);
68 return NAsyncWorkCallback(env, thisVar, cb).Schedule(PROCEDURE_LOCALCAPABILITIES_NAME, cbExec, cbCompl).val_;
69 }
70 }
71
CheckDataList(const LibN::NVal & data)72 static bool CheckDataList(const LibN::NVal &data)
73 {
74 LibN::NVal name = data.GetProp(BConstants::BUNDLE_NAME);
75 if (name.val_ == nullptr) {
76 return false;
77 }
78 auto [succ, str, ignore] = name.ToUTF8String();
79 if (!succ) {
80 return false;
81 }
82
83 LibN::NVal time = data.GetProp(BConstants::LAST_INCREMENTAL_TIME);
84 if (time.val_ == nullptr) {
85 return false;
86 }
87 tie(succ, ignore) = time.ToInt64();
88 if (!succ) {
89 return false;
90 }
91 return true;
92 }
93
ParseDataList(napi_env env,const napi_value & value)94 static std::tuple<bool, std::vector<BIncrementalData>> ParseDataList(napi_env env, const napi_value& value)
95 {
96 uint32_t size = 0;
97 napi_status status = napi_get_array_length(env, value, &size);
98 if (status != napi_ok) {
99 HILOGE("Get array length failed!");
100 return {false, {}};
101 }
102 if (size == 0) {
103 HILOGI("array length is zero!");
104 return {true, {}};
105 }
106
107 napi_value result;
108 std::vector<BIncrementalData> backupData;
109 for (uint32_t i = 0; i < size; i++) {
110 status = napi_get_element(env, value, i, &result);
111 if (status != napi_ok) {
112 HILOGE("Get element failed! index is :%{public}u", i);
113 return {false, {}};
114 } else {
115 NVal element(env, result);
116 if (!CheckDataList(element)) {
117 HILOGE("bundles are invalid!");
118 return {false, {}};
119 }
120 IncrementalBackupData data(element);
121 backupData.emplace_back(data.bundleName,
122 data.lastIncrementalTime,
123 data.manifestFd,
124 data.parameters,
125 data.priority);
126 }
127 }
128 return {true, backupData};
129 }
130
AsyncDataList(napi_env env,const NFuncArg & funcArg)131 static napi_value AsyncDataList(napi_env env, const NFuncArg& funcArg)
132 {
133 HILOGD("called LocalCapabilities::AsyncDataList begin");
134
135 auto [succ, bundles] = ParseDataList(env, funcArg[NARG_POS::FIRST]);
136 if (!succ) {
137 HILOGE("bundles array invalid.");
138 NError(BError(BError::Codes::SDK_INVAL_ARG, "bundles array invalid.").GetCode()).ThrowErr(env);
139 return nullptr;
140 }
141
142 auto fd = make_shared<UniqueFd>();
143 auto cbExec = [fd, bundles { move(bundles) }]() -> NError {
144 HILOGI("called LocalCapabilities::AsyncDataList cbExec");
145 ServiceProxy::InvaildInstance();
146 auto proxy = ServiceProxy::GetInstance();
147 if (!proxy) {
148 HILOGI("called LocalCapabilities::AsyncDataList cbExec, failed to get proxy");
149 return NError(errno);
150 }
151 *fd = proxy->GetLocalCapabilitiesIncremental(bundles);
152 return NError(ERRNO_NOERR);
153 };
154 auto cbCompl = [fd](napi_env env, NError err) -> NVal {
155 if (err) {
156 return {env, err.GetNapiErr(env)};
157 }
158 NVal obj = NVal::CreateObject(env);
159 obj.AddProp({NVal::DeclareNapiProperty(BConstants::FD.c_str(), NVal::CreateInt32(env, fd->Release()).val_)});
160 return {obj};
161 };
162
163 HILOGI("called LocalCapabilities::Async::promise");
164 NVal thisVar(env, funcArg.GetThisVar());
165 return NAsyncWorkPromise(env, thisVar).Schedule(PROCEDURE_LOCALCAPABILITIES_NAME, cbExec, cbCompl).val_;
166 }
167
Async(napi_env env,napi_callback_info info)168 napi_value PropNOperation::Async(napi_env env, napi_callback_info info)
169 {
170 HILOGD("called LocalCapabilities::Async begin");
171 if (!SAUtils::CheckBackupPermission()) {
172 HILOGE("Has not permission!");
173 NError(E_PERMISSION).ThrowErr(env);
174 return nullptr;
175 }
176 if (!SAUtils::IsSystemApp()) {
177 HILOGE("System App check fail!");
178 NError(E_PERMISSION_SYS).ThrowErr(env);
179 return nullptr;
180 }
181 NFuncArg funcArg(env, info);
182 if (!funcArg.InitArgs(NARG_CNT::ZERO, NARG_CNT::ONE)) {
183 HILOGE("Number of arguments unmatched.");
184 NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
185 return nullptr;
186 }
187
188 if (funcArg.GetArgc() == 1) {
189 bool result = 0;
190 napi_status status = napi_is_array(env, funcArg[NARG_POS::FIRST], &result);
191 if (status == napi_ok && result) {
192 return AsyncDataList(env, funcArg);
193 }
194 }
195
196 return AsyncCallback(env, funcArg);
197 }
198
DoGetBackupInfo(napi_env env,napi_callback_info info)199 napi_value PropNOperation::DoGetBackupInfo(napi_env env, napi_callback_info info)
200 {
201 HILOGD("called DoGetBackupInfo begin");
202 if (!SAUtils::CheckBackupPermission()) {
203 HILOGE("Has not permission!");
204 NError(E_PERMISSION).ThrowErr(env);
205 return nullptr;
206 }
207 if (!SAUtils::IsSystemApp()) {
208 HILOGE("System App check fail!");
209 NError(E_PERMISSION_SYS).ThrowErr(env);
210 return nullptr;
211 }
212 std::string result;
213 NFuncArg funcArg(env, info);
214 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
215 HILOGE("Number of arguments unmatched.");
216 NError(BError(BError::Codes::SDK_INVAL_ARG, "Number of arguments unmatched.").GetCode()).ThrowErr(env);
217 return nullptr;
218 }
219 NVal jsBundle(env, funcArg[NARG_POS::FIRST]);
220 auto [succ, bundle, size] = jsBundle.ToUTF8String();
221 if (!succ) {
222 HILOGE("First argument is not string.");
223 NError(EINVAL).ThrowErr(env);
224 return nullptr;
225 }
226
227 ServiceProxy::InvaildInstance();
228 auto proxy = ServiceProxy::GetInstance();
229 if (!proxy) {
230 HILOGE("called DoGetBackupInfo,failed to get proxy");
231 return nullptr;
232 }
233 std::string bundleName = bundle.get();
234 ErrCode errcode = proxy->GetBackupInfo(bundleName, result);
235 if (errcode != 0) {
236 HILOGE("proxy->GetBackupInfo faild.");
237 return nullptr;
238 }
239
240 napi_value nResult;
241 napi_status status = napi_create_string_utf8(env, result.c_str(), result.size(), &nResult);
242 if (status != napi_ok) {
243 HILOGE("napi_create_string_utf8 faild.");
244 return nullptr;
245 }
246 HILOGI("DoGetBackupInfo success with result: %{public}s", result.c_str());
247 return nResult;
248 }
249
UpdateSendRate(std::string & bundleName,int32_t sendRate)250 bool PropNOperation::UpdateSendRate(std::string &bundleName, int32_t sendRate)
251 {
252 bool result = false;
253 ServiceProxy::InvaildInstance();
254 auto proxy = ServiceProxy::GetInstance();
255 if (!proxy) {
256 HILOGE("called UpdateSendRate,failed to get proxy");
257 return result;
258 }
259 ErrCode errCode = proxy->UpdateSendRate(bundleName, sendRate, result);
260 if (errCode != 0) {
261 HILOGE("Proxy execute UpdateSendRate failed. errCode:%{public}d", errCode);
262 return result;
263 }
264 return result;
265 }
266
UpdateTimer(std::string & bundleName,uint32_t timeout)267 bool PropNOperation::UpdateTimer(std::string &bundleName, uint32_t timeout)
268 {
269 bool result = false;
270 ServiceProxy::InvaildInstance();
271 auto proxy = ServiceProxy::GetInstance();
272 if (!proxy) {
273 HILOGE("called DoUpdateTimer,failed to get proxy");
274 return result;
275 }
276 ErrCode errcode = proxy->UpdateTimer(bundleName, timeout, result);
277 if (errcode != 0) {
278 HILOGE("proxy->UpdateTimer faild.");
279 return result;
280 }
281 return result;
282 }
283
DoUpdateTimer(napi_env env,napi_callback_info info)284 napi_value PropNOperation::DoUpdateTimer(napi_env env, napi_callback_info info)
285 {
286 HILOGD("called DoUpdateTimer begin");
287 if (!SAUtils::CheckBackupPermission()) {
288 HILOGE("Has not permission!");
289 NError(E_PERMISSION).ThrowErr(env);
290 return nullptr;
291 }
292 if (!SAUtils::IsSystemApp()) {
293 HILOGE("System App check fail!");
294 NError(E_PERMISSION_SYS).ThrowErr(env);
295 return nullptr;
296 }
297 NFuncArg funcArg(env, info);
298 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
299 HILOGE("Number of arguments unmatched.");
300 NError(E_PARAMS).ThrowErr(env);
301 return nullptr;
302 }
303 NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
304 auto [succStr, bundle, sizeStr] = jsBundleStr.ToUTF8String();
305 if (!succStr) {
306 HILOGE("First argument is not string.");
307 NError(E_PARAMS).ThrowErr(env);
308 return nullptr;
309 }
310 NVal jsBundleInt(env, funcArg[NARG_POS::SECOND]);
311 auto [succInt, time] = jsBundleInt.ToInt32();
312 if (!succInt || time < 0 || time > static_cast<int32_t>(BConstants::MAX_UPDATE_TIMER)) {
313 HILOGE("Second argument is not number.");
314 NError(E_PARAMS).ThrowErr(env);
315 return nullptr;
316 }
317
318 std::string bundleName = bundle.get();
319 uint32_t timeout = static_cast<uint32_t>(time);
320 bool result = UpdateTimer(bundleName, timeout);
321
322 napi_value nResult;
323 napi_status status = napi_get_boolean(env, result, &nResult);
324 if (status != napi_ok) {
325 HILOGE("napi_get_boolean faild.");
326 return nullptr;
327 }
328 HILOGI("DoUpdateTimer success with result: %{public}d", result);
329 return nResult;
330 }
331
DoUpdateSendRate(napi_env env,napi_callback_info info)332 napi_value PropNOperation::DoUpdateSendRate(napi_env env, napi_callback_info info)
333 {
334 HILOGD("called DoUpdateSendRate begin");
335 if (!SAUtils::CheckBackupPermission()) {
336 HILOGE("Has not permission!");
337 NError(E_PERMISSION).ThrowErr(env);
338 return nullptr;
339 }
340 if (!SAUtils::IsSystemApp()) {
341 HILOGE("System App check fail!");
342 NError(E_PERMISSION_SYS).ThrowErr(env);
343 return nullptr;
344 }
345 NFuncArg funcArg(env, info);
346 if (!funcArg.InitArgs(NARG_CNT::ONE, NARG_CNT::TWO)) {
347 HILOGE("Number of arguments unmatched.");
348 NError(E_PARAMS).ThrowErr(env);
349 return nullptr;
350 }
351 NVal jsBundleStr(env, funcArg[NARG_POS::FIRST]);
352 auto [succStr, bundle, sizeStr] = jsBundleStr.ToUTF8String();
353 if (!succStr) {
354 HILOGE("First argument is not string.");
355 NError(E_PARAMS).ThrowErr(env);
356 return nullptr;
357 }
358 std::string bundleName = bundle.get();
359 NVal jsBundleInt(env, funcArg[NARG_POS::SECOND]);
360 auto [succInt, jsRate] = jsBundleInt.ToInt32();
361 if (!succInt || jsRate < 0) {
362 HILOGE("Second argument is invalid. bundleName:%{public}s", bundleName.c_str());
363 NError(E_PARAMS).ThrowErr(env);
364 return nullptr;
365 }
366 int32_t sendFdRate = static_cast<int32_t>(jsRate);
367 if (sendFdRate > BConstants::MAX_FD_SEND_RATE) {
368 HILOGI("sendFdRate is too large, %{public}d", sendFdRate);
369 sendFdRate = BConstants::MAX_FD_SEND_RATE;
370 }
371 bool result = UpdateSendRate(bundleName, sendFdRate);
372 napi_value nResult;
373 napi_status status = napi_get_boolean(env, result, &nResult);
374 if (status != napi_ok) {
375 HILOGE("napi_get_boolean failed.");
376 return nullptr;
377 }
378 HILOGI("DoUpdateSendRate success with result: %{public}d", result);
379 return nResult;
380 }
381 } // namespace OHOS::FileManagement::Backup
382