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
16 #include "js_config.h"
17
18 #include <cstddef>
19 #include <memory>
20
21 #include "cloud_manager.h"
22 #include "cloud_service.h"
23 #include "js_error_utils.h"
24 #include "js_utils.h"
25 #include "logger.h"
26 #include "napi_queue.h"
27
28 using namespace OHOS::Rdb;
29 using namespace OHOS::CloudData;
30 using namespace OHOS::AppDataMgrJsKit;
JsConfig()31 JsConfig::JsConfig()
32 {
33 }
34
~JsConfig()35 JsConfig::~JsConfig()
36 {
37 }
38
39 /*
40 * [JS API Prototype]
41 * [AsyncCallback]
42 * enableCloud(accountId: string, switches: {[bundleName: string]: boolean}, callback: AsyncCallback<void>): void;
43 * [Promise]
44 * enableCloud(accountId: string, switches: {[bundleName: string]: boolean}): Promise<void>;
45 */
EnableCloud(napi_env env,napi_callback_info info)46 napi_value JsConfig::EnableCloud(napi_env env, napi_callback_info info)
47 {
48 struct EnableCloudContext : public ContextBase {
49 std::string accountId;
50 std::map<std::string, bool> tempSwitches;
51 std::map<std::string, int32_t> switches;
52 };
53 auto ctxt = std::make_shared<EnableCloudContext>();
54 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
55 // required 2 arguments :: <accountId> <switches>
56 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
57 // 0 is the index of argument accountId, 1 is the index of argument switches
58 int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId);
59 ASSERT_BUSINESS_ERR(
60 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string.");
61 status = JSUtils::Convert2Value(env, argv[1], ctxt->tempSwitches);
62 ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT,
63 "The type of switches must be {[bundleName: string]: boolean}.");
64 for (auto item : ctxt->tempSwitches) {
65 ctxt->switches[item.first] = item.second ? CloudService::Switch::SWITCH_ON
66 : CloudService::Switch::SWITCH_OFF;
67 }
68 });
69
70 ASSERT_NULL(!ctxt->isThrowError, "EnableCloud exit");
71
72 auto execute = [ctxt]() {
73 auto [state, proxy] = CloudManager::GetInstance().GetCloudService();
74 if (proxy == nullptr) {
75 if (state != CloudService::SERVER_UNAVAILABLE) {
76 state = CloudService::NOT_SUPPORT;
77 }
78 ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
79 ? napi_ok
80 : napi_generic_failure;
81 return;
82 }
83 int32_t cStatus = proxy->EnableCloud(ctxt->accountId, ctxt->switches);
84 LOG_DEBUG("EnableCloud return %{public}d", cStatus);
85 ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
86 ? napi_ok
87 : napi_generic_failure;
88 };
89 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
90 }
91
92 /*
93 * [JS API Prototype]
94 * [AsyncCallback]
95 * disableCloud(accountId: string, callback: AsyncCallback<void>): void;
96 * [Promise]
97 * disableCloud(accountId: string): Promise<void>;
98 */
DisableCloud(napi_env env,napi_callback_info info)99 napi_value JsConfig::DisableCloud(napi_env env, napi_callback_info info)
100 {
101 struct DisableCloudContext : public ContextBase {
102 std::string accountId;
103 };
104 auto ctxt = std::make_shared<DisableCloudContext>();
105 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
106 // required 1 arguments :: <accountId>
107 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
108 // 0 is the index of argument accountId
109 int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId);
110 ASSERT_BUSINESS_ERR(
111 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string.");
112 });
113
114 ASSERT_NULL(!ctxt->isThrowError, "DisableCloud exit");
115
116 auto execute = [ctxt]() {
117 auto [state, proxy] = CloudManager::GetInstance().GetCloudService();
118 if (proxy == nullptr) {
119 if (state != CloudService::SERVER_UNAVAILABLE) {
120 state = CloudService::NOT_SUPPORT;
121 }
122 ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
123 ? napi_ok
124 : napi_generic_failure;
125 return;
126 }
127 int32_t cStatus = proxy->DisableCloud(ctxt->accountId);
128 LOG_DEBUG("DisableCloud return %{public}d", cStatus);
129 ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
130 ? napi_ok
131 : napi_generic_failure;
132 };
133 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
134 }
135
136 /*
137 * [JS API Prototype]
138 * [AsyncCallback]
139 * changeAppCloudSwitch(accountId: string, bundleName: string, status :boolean,
140 * callback: AsyncCallback<void>): void;
141 * [Promise]
142 * changeAppCloudSwitch(accountId: string, bundleName: string, status :boolean): Promise<void>;
143 */
144
ChangeAppCloudSwitch(napi_env env,napi_callback_info info)145 napi_value JsConfig::ChangeAppCloudSwitch(napi_env env, napi_callback_info info)
146 {
147 struct ChangeAppSwitchContext : public ContextBase {
148 std::string accountId;
149 std::string bundleName;
150 CloudService::Switch state;
151 };
152 auto ctxt = std::make_shared<ChangeAppSwitchContext>();
153 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
154 // required 3 arguments :: <accountId> <bundleName> <state>
155 ASSERT_BUSINESS_ERR(ctxt, argc >= 3, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
156 // 0 is the index of argument accountId, 1 is the index of argument bundleName, 2 is the index of argument state
157 int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId);
158 ASSERT_BUSINESS_ERR(
159 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string.");
160 status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName);
161 ASSERT_BUSINESS_ERR(
162 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of bundleName must be string.");
163 bool state = false;
164 // 2 is the index of argument state
165 status = JSUtils::Convert2Value(env, argv[2], state);
166 ASSERT_BUSINESS_ERR(
167 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of status must be boolean.");
168 ctxt->state = state ? CloudService::Switch::SWITCH_ON : CloudService::Switch::SWITCH_OFF;
169 });
170
171 ASSERT_NULL(!ctxt->isThrowError, "ChangeAppCloudSwitch exit");
172
173 auto execute = [ctxt]() {
174 auto [state, proxy] = CloudManager::GetInstance().GetCloudService();
175 if (proxy == nullptr) {
176 if (state != CloudService::SERVER_UNAVAILABLE) {
177 state = CloudService::NOT_SUPPORT;
178 }
179 ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
180 ? napi_ok
181 : napi_generic_failure;
182 return;
183 }
184 int32_t cStatus = proxy->ChangeAppSwitch(ctxt->accountId, ctxt->bundleName, ctxt->state);
185 LOG_DEBUG("ChangeAppCloudSwitch return %{public}d", cStatus);
186 ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
187 ? napi_ok
188 : napi_generic_failure;
189 };
190 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
191 }
192
193 /*
194 * [JS API Prototype]
195 * [AsyncCallback]
196 * clean(accountId: string, appActions: {[bundleName: string]: Action}, callback: AsyncCallback<void>): void;
197 * [Promise]
198 * clean(accountId: string, appActions: {[bundleName: string]: Action}): Promise<void>;
199 */
Clean(napi_env env,napi_callback_info info)200 napi_value JsConfig::Clean(napi_env env, napi_callback_info info)
201 {
202 struct CleanContext : public ContextBase {
203 std::string accountId;
204 std::map<std::string, int32_t> appActions;
205 };
206 auto ctxt = std::make_shared<CleanContext>();
207 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
208 // required 2 arguments :: <accountId> <appActions>
209 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
210 // 0 is the index of argument accountId, 1 is the index of argument
211 int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId);
212 ASSERT_BUSINESS_ERR(
213 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string.");
214 status = JSUtils::Convert2Value(env, argv[1], ctxt->appActions);
215 ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT,
216 "The type of actions must be {[bundleName: string]: int32_t}.");
217 for (auto item : ctxt->appActions) {
218 ASSERT_BUSINESS_ERR(ctxt, ValidSubscribeType(item.second), Status::INVALID_ARGUMENT,
219 "Action in map appActions is incorrect.");
220 }
221 });
222
223 ASSERT_NULL(!ctxt->isThrowError, "Clean exit");
224
225 auto execute = [ctxt]() {
226 auto [state, proxy] = CloudManager::GetInstance().GetCloudService();
227 if (proxy == nullptr) {
228 if (state != CloudService::SERVER_UNAVAILABLE) {
229 state = CloudService::NOT_SUPPORT;
230 }
231 ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
232 ? napi_ok
233 : napi_generic_failure;
234 return;
235 }
236 int32_t cStatus = proxy->Clean(ctxt->accountId, ctxt->appActions);
237 LOG_DEBUG("Clean return %{public}d", cStatus);
238 ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
239 ? napi_ok
240 : napi_generic_failure;
241 };
242 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
243 }
244
245 /*
246 * [JS API Prototype]
247 * [AsyncCallback]
248 * notifyDataChange(accountId: string, bundleName: string, callback: AsyncCallback<void>): void;
249 * [Promise]
250 * notifyDataChange(accountId: string, bundleName: string): Promise<void>;
251 */
NotifyDataChange(napi_env env,napi_callback_info info)252 napi_value JsConfig::NotifyDataChange(napi_env env, napi_callback_info info)
253 {
254 struct ChangeAppSwitchContext : public ContextBase {
255 std::string accountId;
256 std::string bundleName;
257 };
258 auto ctxt = std::make_shared<ChangeAppSwitchContext>();
259 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
260 // required 2 arguments :: <accountId> <bundleName>
261 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect.");
262 // 0 is the index of argument accountId, 1 is the index of argument bundleName
263 int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId);
264 ASSERT_BUSINESS_ERR(
265 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string.");
266 status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName);
267 ASSERT_BUSINESS_ERR(
268 ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of bundleName must be string.");
269 });
270
271 ASSERT_NULL(!ctxt->isThrowError, "NotifyDataChange exit");
272
273 auto execute = [ctxt]() {
274 auto [state, proxy] = CloudManager::GetInstance().GetCloudService();
275 if (proxy == nullptr) {
276 if (state != CloudService::SERVER_UNAVAILABLE) {
277 state = CloudService::NOT_SUPPORT;
278 }
279 ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
280 ? napi_ok
281 : napi_generic_failure;
282 return;
283 }
284 int32_t cStatus = proxy->NotifyDataChange(ctxt->accountId, ctxt->bundleName);
285 LOG_DEBUG("NotifyDataChange return %{public}d", cStatus);
286 ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS)
287 ? napi_ok
288 : napi_generic_failure;
289 };
290 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
291 }
292
New(napi_env env,napi_callback_info info)293 napi_value JsConfig::New(napi_env env, napi_callback_info info)
294 {
295 napi_value self = nullptr;
296 size_t argc = ARGC_MAX;
297 napi_value argv[ARGC_MAX] = { 0 };
298 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &self, nullptr));
299 if (self == nullptr) {
300 napi_new_instance(env, JSUtils::GetClass(env, "ohos.cloudData", "Config"), argc, argv, &self);
301 return self;
302 }
303
304 auto finalize = [](napi_env env, void *data, void *hint) {
305 LOG_DEBUG("cloudConfig finalize.");
306 auto *config = reinterpret_cast<JsConfig *>(data);
307 ASSERT_VOID(config != nullptr, "finalize null!");
308 delete config;
309 };
310 JsConfig *cloudConfig = new (std::nothrow) JsConfig();
311 ASSERT_ERR(env, cloudConfig != nullptr, Status::INVALID_ARGUMENT, "no memory for cloudConfig.");
312 napi_status status = napi_wrap(env, self, cloudConfig, finalize, nullptr, nullptr);
313 if (status != napi_ok) {
314 LOG_ERROR("JsConfig::Initialize napi_wrap failed! code:%{public}d!", status);
315 finalize(env, cloudConfig, nullptr);
316 return nullptr;
317 }
318 return self;
319 }
320
InitConfig(napi_env env,napi_value exports)321 napi_value JsConfig::InitConfig(napi_env env, napi_value exports)
322 {
323 auto lambda = []() -> std::vector<napi_property_descriptor> {
324 std::vector<napi_property_descriptor> properties = {
325 DECLARE_NAPI_STATIC_FUNCTION("enableCloud", JsConfig::EnableCloud),
326 DECLARE_NAPI_STATIC_FUNCTION("disableCloud", JsConfig::DisableCloud),
327 DECLARE_NAPI_STATIC_FUNCTION("changeAppCloudSwitch", JsConfig::ChangeAppCloudSwitch),
328 DECLARE_NAPI_STATIC_FUNCTION("clear", JsConfig::Clean),
329 DECLARE_NAPI_STATIC_FUNCTION("clean", JsConfig::Clean),
330 DECLARE_NAPI_STATIC_FUNCTION("notifyDataChange", JsConfig::NotifyDataChange),
331 };
332 return properties;
333 };
334 auto jsCtor = JSUtils::DefineClass(env, "ohos.data.cloudData", "Config", lambda, JsConfig::New);
335 NAPI_CALL(env, napi_set_named_property(env, exports, "Config", jsCtor));
336 return exports;
337 }