1 /*
2  * Copyright (c) 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 #define LOG_TAG "JSCloudShare"
16 #include "js_cloud_share.h"
17 
18 #include "cache_result_set.h"
19 #include "cloud_manager.h"
20 #include "cloud_service.h"
21 #include "cloud_types.h"
22 #include "js_cloud_utils.h"
23 #include "js_error_utils.h"
24 #include "js_utils.h"
25 #include "logger.h"
26 #include "napi_queue.h"
27 #include "rdb_predicates.h"
28 #include "result_set.h"
29 
30 namespace OHOS::CloudData {
31 using namespace OHOS::NativeRdb;
32 using namespace OHOS::AppDataMgrJsKit;
33 /*
34  * [JS API Prototype]
35  * [AsyncCallback]
36  *      allocResourceAndShare(storeId: string, predicates: relationalStore.RdbPredicates,
37  *          participants: Array<Participant>, callback: AsyncCallback<relationalStore.ResultSet>): void;
38  *      allocResourceAndShare(storeId: string, predicates: relationalStore.RdbPredicates,
39  *          participants: Array<Participant>, columns: Array<string>,
40  *          callback: AsyncCallback<relationalStore.ResultSet> ): void;
41  *
42  * [Promise]
43  *     allocResourceAndShare(storeId: string, predicates: relationalStore.RdbPredicates,
44  *         participants: Array<Participant>, columns?: Array<string>): Promise<relationalStore.ResultSet>;
45  */
AllocResourceAndShare(napi_env env,napi_callback_info info)46 napi_value AllocResourceAndShare(napi_env env, napi_callback_info info)
47 {
48     struct AllocResAndShareContext : public ContextBase {
49         std::string storeId;
50         Participants participants;
51         std::vector<std::string> columns;
52         std::shared_ptr<RdbPredicates> predicates = nullptr;
53         std::shared_ptr<ResultSet> resultSet;
54     };
55     auto ctxt = std::make_shared<AllocResAndShareContext>();
56     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
57         // allocResourceAndShare storeId, predicates, participants 3 required parameter, columns 1 Optional parameter
58         ASSERT_BUSINESS_ERR(ctxt, argc >= 3, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
59         int status = JSUtils::Convert2Value(env, argv[0], ctxt->storeId);
60         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->storeId.empty(), Status::INVALID_ARGUMENT,
61             "The type of storeId must be string and not empty.");
62         // 'argv[1]' represents a RdbPredicates parameter
63         status = JSUtils::Convert2Value(env, argv[1], ctxt->predicates);
64         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT,
65             "The type of predicates must be relationalStore.RdbPredicates");
66         // 'argv[2]' represents a Participants parameter
67         status = JSUtils::Convert2Value(env, argv[2], ctxt->participants);
68         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(), Status::INVALID_ARGUMENT,
69             "The type of participants must be Array<Participant> and not empty.");
70         // 'argv[3]' represents an optional std::vector<std::string> parameter
71         if (argc > 3 && !JSUtils::IsNull(env, argv[3])) {
72             // 'argv[3]' represents the columns optional parameter
73             status = JSUtils::Convert2Value(env, argv[3], ctxt->columns);
74             ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK,
75                 Status::INVALID_ARGUMENT, "The type of columns must be Array<string>.");
76         }
77     });
78     ASSERT_NULL(!ctxt->isThrowError, "AllocResourceAndShare exit");
79     auto execute = [env, ctxt]() {
80         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
81         if (proxy == nullptr) {
82             if (status != CloudService::SERVER_UNAVAILABLE) {
83                 status = CloudService::NOT_SUPPORT;
84             }
85             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
86                                ? napi_ok: napi_generic_failure;
87             return;
88         }
89 
90         auto [result, valueBuckets] = proxy->AllocResourceAndShare(
91             ctxt->storeId, ctxt->predicates->GetDistributedPredicates(), ctxt->columns, ctxt->participants);
92         LOG_DEBUG("AllocResourceAndShare result: %{public}d, size:%{public}zu", result, valueBuckets.size());
93         ctxt->resultSet = std::make_shared<CacheResultSet>(std::move(valueBuckets));
94         ctxt->status =
95             (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure;
96     };
97     auto output = [env, ctxt](napi_value& result) {
98         result = JSUtils::Convert2JSValue(env, ctxt->resultSet);
99         ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed");
100     };
101     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
102 }
103 
104 /*
105  * [JS API Prototype]
106  * [AsyncCallback]
107  *     share(sharingRes: string, participants: Array<Participant>,
108  *         callback: AsyncCallback<Result<Array<Result<Participant>>>>): void;
109  *
110  * [Promise]
111  *     share(sharingRes: string, participants: Array<Participant>): Promise<Result<Array<Result<Participant>>>>;
112  */
Share(napi_env env,napi_callback_info info)113 napi_value Share(napi_env env, napi_callback_info info)
114 {
115     struct ShareContext : public ContextBase {
116         std::string sharingRes;
117         Participants participants;
118         Results results;
119     };
120     auto ctxt = std::make_shared<ShareContext>();
121     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
122         // ShareContext have sharingRes, participants 2 required parameter
123         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
124         int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes);
125         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(),
126             Status::INVALID_ARGUMENT, "The type of sharingRes must be string and not empty.");
127         status = JSUtils::Convert2Value(env, argv[1], ctxt->participants);
128         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(),
129             Status::INVALID_ARGUMENT, "The type of participants must be Array<Participant> and not empty.");
130     });
131     ASSERT_NULL(!ctxt->isThrowError, "share exit");
132 
133     auto execute = [env, ctxt]() {
134         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
135         if (proxy == nullptr) {
136             if (status != CloudService::SERVER_UNAVAILABLE) {
137                 status = CloudService::NOT_SUPPORT;
138             }
139             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
140                 napi_ok : napi_generic_failure;
141             return;
142         }
143         int32_t result = proxy->Share(ctxt->sharingRes, ctxt->participants, ctxt->results);
144         LOG_DEBUG("share result %{public}d", result);
145         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
146             napi_ok : napi_generic_failure;
147     };
148     auto output = [env, ctxt](napi_value& result) {
149         result = JSUtils::Convert2JSValue(env, ctxt->results);
150         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
151     };
152     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
153 }
154 
155 /*
156  * [JS API Prototype]
157  * [AsyncCallback]
158  *     unshare(sharingRes: string, participants: Array<Participant>,
159  *         callback: AsyncCallback<Result<Array<Result<Participant>>>>): void;
160  *
161  * [Promise]
162  *     unshare(sharingRes: string, participants: Array<Participant>): Promise<Result<Array<Result<Participant>>>>;
163  */
Unshare(napi_env env,napi_callback_info info)164 napi_value Unshare(napi_env env, napi_callback_info info)
165 {
166     struct UnshareContext : public ContextBase {
167         std::string sharingRes;
168         Participants participants;
169         Results results;
170     };
171     auto ctxt = std::make_shared<UnshareContext>();
172     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
173         // ShareContext have sharingRes, participants 2 required parameter
174         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
175         int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes);
176         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(),
177             Status::INVALID_ARGUMENT, "The type of sharingRes must be string and not empty.");
178         status = JSUtils::Convert2Value(env, argv[1], ctxt->participants);
179         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(),
180             Status::INVALID_ARGUMENT, "The type of participants must be Array<Participant> and not empty.");
181     });
182     ASSERT_NULL(!ctxt->isThrowError, "unShare exit");
183     auto execute = [env, ctxt]() {
184         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
185         if (proxy == nullptr) {
186             if (status != CloudService::SERVER_UNAVAILABLE) {
187                 status = CloudService::NOT_SUPPORT;
188             }
189             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
190                 napi_ok : napi_generic_failure;
191             return;
192         }
193         int32_t result = proxy->Unshare(ctxt->sharingRes, ctxt->participants, ctxt->results);
194         LOG_DEBUG("unshare result %{public}d", result);
195         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
196             napi_ok : napi_generic_failure;
197     };
198     auto output = [env, ctxt](napi_value& result) {
199         result = JSUtils::Convert2JSValue(env, ctxt->results);
200         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
201     };
202     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
203 }
204 
205 /*
206  * [JS API Prototype]
207  * [AsyncCallback]
208  *     exit(sharingRes: string, callback: AsyncCallback<Result<void>>): void;
209  *
210  * [Promise]
211  *     exit(sharingRes: string): Promise<Result<void>>;
212  */
Exit(napi_env env,napi_callback_info info)213 napi_value Exit(napi_env env, napi_callback_info info)
214 {
215     struct ExitContext : public ContextBase {
216         std::string sharingRes;
217         std::pair<int32_t, std::string> result;
218     };
219     auto ctxt = std::make_shared<ExitContext>();
220     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
221         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
222         int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes);
223         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(),
224             Status::INVALID_ARGUMENT, "The type of sharingRes must be string and not empty.");
225     });
226     ASSERT_NULL(!ctxt->isThrowError, "exit exit");
227     auto execute = [env, ctxt]() {
228         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
229         if (proxy == nullptr) {
230             if (status != CloudService::SERVER_UNAVAILABLE) {
231                 status = CloudService::NOT_SUPPORT;
232             }
233             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
234                 napi_ok : napi_generic_failure;
235             return;
236         }
237         int32_t result = proxy->Exit(ctxt->sharingRes, ctxt->result);
238         LOG_DEBUG("exit sharing result %{public}d", result);
239         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
240             napi_ok : napi_generic_failure;
241     };
242     auto output = [env, ctxt](napi_value& result) {
243         result = JSUtils::Convert2JSValue(env, ctxt->result);
244         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
245     };
246     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
247 }
248 
249 /*
250  * [JS API Prototype]
251  * [AsyncCallback]
252  *     changePrivilege(sharingRes: string, participants: Array<Participant>,
253  *         callback: AsyncCallback<Result<Array<Result<Participant>>>>): void;
254  *
255  * [Promise]
256  *     changePrivilege(
257  *         sharingRes: string,
258  *         participants: Array<Participant>): Promise<Result<Array<Result<Participant>>>>;
259  */
ChangePrivilege(napi_env env,napi_callback_info info)260 napi_value ChangePrivilege(napi_env env, napi_callback_info info)
261 {
262     struct ChangePrivilegeContext : public ContextBase {
263         std::string sharingRes;
264         Participants participants;
265         Results results;
266     };
267     auto ctxt = std::make_shared<ChangePrivilegeContext>();
268     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
269         // ShareContext have sharingRes, participants 2 required parameter
270         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
271         int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes);
272         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(),
273             Status::INVALID_ARGUMENT, "The type of sharingRes must be string and not empty.");
274         status = JSUtils::Convert2Value(env, argv[1], ctxt->participants);
275         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(),
276             Status::INVALID_ARGUMENT, "The type of participants must be Array<Participant> and not empty.");
277     });
278     ASSERT_NULL(!ctxt->isThrowError, "changePrivilege exit");
279     auto execute = [env, ctxt]() {
280         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
281         if (proxy == nullptr) {
282             if (status != CloudService::SERVER_UNAVAILABLE) {
283                 status = CloudService::NOT_SUPPORT;
284             }
285             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
286                 napi_ok : napi_generic_failure;
287             return;
288         }
289         int32_t result = proxy->ChangePrivilege(ctxt->sharingRes, ctxt->participants, ctxt->results);
290         LOG_DEBUG("change privilege result %{public}d", result);
291         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
292             napi_ok : napi_generic_failure;
293     };
294     auto output = [env, ctxt](napi_value& result) {
295         result = JSUtils::Convert2JSValue(env, ctxt->results);
296         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
297     };
298     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
299 }
300 
301 /*
302  * [JS API Prototype]
303  * [AsyncCallback]
304  *     queryParticipants(sharingRes: string, callback: AsyncCallback<Result<Array<Participant>>>): void;
305  *
306  * [Promise]
307  *     queryParticipants(sharingRes: string): Promise<Result<Array<Participant>>>;
308  */
Query(napi_env env,napi_callback_info info)309 napi_value Query(napi_env env, napi_callback_info info)
310 {
311     struct QueryContext : public ContextBase {
312         std::string sharingRes;
313         QueryResults results;
314     };
315     auto ctxt = std::make_shared<QueryContext>();
316     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
317         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
318         int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes);
319         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(),
320             Status::INVALID_ARGUMENT, "The type of sharingRes must be string and not empty.");
321     });
322     ASSERT_NULL(!ctxt->isThrowError, "query exit");
323     auto execute = [env, ctxt]() {
324         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
325         if (proxy == nullptr) {
326             if (status != CloudService::SERVER_UNAVAILABLE) {
327                 status = CloudService::NOT_SUPPORT;
328             }
329             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
330                 napi_ok : napi_generic_failure;
331             return;
332         }
333         int32_t result = proxy->Query(ctxt->sharingRes, ctxt->results);
334         LOG_DEBUG("query participants result %{public}d", result);
335         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
336             napi_ok : napi_generic_failure;
337     };
338     auto output = [env, ctxt](napi_value& result) {
339         result = JSUtils::Convert2JSValue(env, ctxt->results);
340         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
341     };
342     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
343 }
344 
345 /*
346  * [JS API Prototype]
347  * [AsyncCallback]
348  *     queryParticipantsByInvitation(invitationCode: string,
349  *         callback: AsyncCallback<Result<Array<Participant>>>): void;
350  *
351  * [Promise]
352  *     queryParticipantsByInvitation(invitationCode: string): Promise<Result<Array<Participant>>>;
353  */
QueryByInvitation(napi_env env,napi_callback_info info)354 napi_value QueryByInvitation(napi_env env, napi_callback_info info)
355 {
356     struct QueryByInvitationContext : public ContextBase {
357         std::string invitationCode;
358         QueryResults results;
359     };
360     auto ctxt = std::make_shared<QueryByInvitationContext>();
361     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
362         ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
363         int status = JSUtils::Convert2Value(env, argv[0], ctxt->invitationCode);
364         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->invitationCode.empty(),
365             Status::INVALID_ARGUMENT, "The type of invitationCode must be string and not empty.");
366     });
367     ASSERT_NULL(!ctxt->isThrowError, "queryByInvitation exit");
368     auto execute = [env, ctxt]() {
369         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
370         if (proxy == nullptr) {
371             if (status != CloudService::SERVER_UNAVAILABLE) {
372                 status = CloudService::NOT_SUPPORT;
373             }
374             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
375                 napi_ok : napi_generic_failure;
376             return;
377         }
378         int32_t result = proxy->QueryByInvitation(ctxt->invitationCode, ctxt->results);
379         LOG_DEBUG("query participants by invitation result %{public}d", result);
380         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
381             napi_ok : napi_generic_failure;
382     };
383     auto output = [env, ctxt](napi_value& result) {
384         result = JSUtils::Convert2JSValue(env, ctxt->results);
385         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
386     };
387     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
388 }
389 
390 /*
391  * [JS API Prototype]
392  * [AsyncCallback]
393  *     confirmInvitation(invitationCode: string, status: Status, callback: AsyncCallback<Result<string>>): void;
394  *
395  * [Promise]
396  *     confirmInvitation(invitationCode: string, status: Status): Promise<Result<string>>;
397  */
ConfirmInvitation(napi_env env,napi_callback_info info)398 napi_value ConfirmInvitation(napi_env env, napi_callback_info info)
399 {
400     struct ConfirmInvitationContext : public ContextBase {
401         std::string invitationCode;
402         int32_t confirmation;
403         std::tuple<int32_t, std::string, std::string> result;
404     };
405     auto ctxt = std::make_shared<ConfirmInvitationContext>();
406     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
407         // ShareContext have sharingRes, participants 2 required parameter
408         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
409         int status = JSUtils::Convert2Value(env, argv[0], ctxt->invitationCode);
410         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->invitationCode.empty(),
411         Status::INVALID_ARGUMENT, "The type of invitationCode must be string and not empty.");
412         int32_t confirmation;
413         status = JSUtils::Convert2ValueExt(env, argv[1], confirmation);
414         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK &&
415                 confirmation > Confirmation::CFM_NIL && confirmation <= Confirmation::CFM_BUTT,
416             Status::INVALID_ARGUMENT, "The type of status must be Status.");
417         ctxt->confirmation = confirmation;
418     });
419     ASSERT_NULL(!ctxt->isThrowError, "confirmInvitation exit");
420     auto execute = [env, ctxt]() {
421         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
422         if (proxy == nullptr) {
423             if (status != CloudService::SERVER_UNAVAILABLE) {
424                 status = CloudService::NOT_SUPPORT;
425             }
426             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
427                 napi_ok : napi_generic_failure;
428             return;
429         }
430         int32_t result = proxy->ConfirmInvitation(ctxt->invitationCode, ctxt->confirmation, ctxt->result);
431         LOG_DEBUG("confirm invitation result %{public}d", result);
432         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
433             napi_ok : napi_generic_failure;
434     };
435     auto output = [env, ctxt](napi_value& result) {
436         result = JSUtils::Convert2JSValue(env, ctxt->result);
437         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
438     };
439     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
440 }
441 
442 /*
443  * [JS API Prototype]
444  * [AsyncCallback]
445  *     changeConfirmation(sharingRes: string, status: Status, callback: AsyncCallback<Result<void>>): void;
446  *
447  * [Promise]
448  *     changeConfirmation(sharingRes: string, status: Status): Promise<Result<void>>;
449  */
ChangeConfirmation(napi_env env,napi_callback_info info)450 napi_value ChangeConfirmation(napi_env env, napi_callback_info info)
451 {
452     struct ChangeConfirmationContext : public ContextBase {
453         std::string sharingRes;
454         int32_t confirmation;
455         std::pair<int32_t, std::string> results;
456     };
457     auto ctxt = std::make_shared<ChangeConfirmationContext>();
458     ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
459         // ShareContext have sharingRes, participants 2 required parameter
460         ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
461         int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes);
462         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(),
463             Status::INVALID_ARGUMENT, "The type of sharingRes must be string and not empty.");
464         int32_t confirmation;
465         status = JSUtils::Convert2ValueExt(env, argv[1], confirmation);
466         ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK &&
467                 confirmation > Confirmation::CFM_NIL && confirmation < Confirmation::CFM_BUTT,
468             Status::INVALID_ARGUMENT, "The type of status must be Status.");
469         ctxt->confirmation = confirmation;
470     });
471     ASSERT_NULL(!ctxt->isThrowError, "changeConfirmation exit");
472     auto execute = [env, ctxt]() {
473         auto [status, proxy] = CloudManager::GetInstance().GetCloudService();
474         if (proxy == nullptr) {
475             if (status != CloudService::SERVER_UNAVAILABLE) {
476                 status = CloudService::NOT_SUPPORT;
477             }
478             ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
479                 napi_ok : napi_generic_failure;
480             return;
481         }
482         int32_t result = proxy->ChangeConfirmation(ctxt->sharingRes, ctxt->confirmation, ctxt->results);
483         LOG_DEBUG("change confirmation result %{public}d", result);
484         ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
485             napi_ok : napi_generic_failure;
486     };
487     auto output = [env, ctxt](napi_value& result) {
488         result = JSUtils::Convert2JSValue(env, ctxt->results);
489         ASSERT_VALUE(ctxt,  result != nullptr, napi_generic_failure, "output failed");
490     };
491     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
492 }
493 
InitCloudSharing(napi_env env,napi_value exports)494 napi_value InitCloudSharing(napi_env env, napi_value exports)
495 {
496     napi_value sharing = nullptr;
497     napi_status status = napi_create_object(env, &sharing);
498     if (status != napi_ok || sharing == nullptr) {
499         return nullptr;
500     }
501     napi_property_descriptor properties[] = {
502         DECLARE_NAPI_FUNCTION("allocResourceAndShare", AllocResourceAndShare),
503         DECLARE_NAPI_FUNCTION("share", Share),
504         DECLARE_NAPI_FUNCTION("unshare", Unshare),
505         DECLARE_NAPI_FUNCTION("exit", Exit),
506         DECLARE_NAPI_FUNCTION("changePrivilege", ChangePrivilege),
507         DECLARE_NAPI_FUNCTION("queryParticipants", Query),
508         DECLARE_NAPI_FUNCTION("queryParticipantsByInvitation", QueryByInvitation),
509         DECLARE_NAPI_FUNCTION("confirmInvitation", ConfirmInvitation),
510         DECLARE_NAPI_FUNCTION("changeConfirmation", ChangeConfirmation),
511     };
512     NAPI_CALL(env, napi_define_properties(env, sharing, sizeof(properties) / sizeof(*properties), properties));
513     NAPI_CALL(env, napi_set_named_property(env, exports, "sharing", sharing));
514     return sharing;
515 }
516 } // namespace OHOS::CloudData