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