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 "calendar_manager_napi.h"
17 #include <optional>
18 #include "calendar_log.h"
19 #include "napi_util.h"
20 #include "napi_queue.h"
21 #include "calendar_napi.h"
22 #include "native_calendar_manager.h"
23 #include "napi_env.h"
24
25 #include "abs_shared_result_set.h"
26 #include "data_ability_helper.h"
27 #include "data_ability_predicates.h"
28 #include "values_bucket.h"
29
30 using namespace OHOS::AppExecFwk;
31 using namespace OHOS::DataShare;
32
33 namespace {
34 const std::string CALENDAR_MANAGER_CLASS_NAME = "CalendarManager";
35 static thread_local napi_ref g_constructorRef = nullptr;
36 constexpr uint32_t INITIAL_REFCOUNT = 1;
37 }
38 namespace OHOS::CalendarApi {
CreateCalendar(napi_env env,napi_callback_info info)39 napi_value CalendarManagerNapi::CreateCalendar(napi_env env, napi_callback_info info)
40 {
41 LOG_INFO("napi CreateCalendar called");
42 struct CreateCalendarContext : public ContextBase {
43 CalendarAccount account;
44 CalendarNapi *calendar;
45 int id;
46 napi_ref ref = nullptr;
47 };
48 auto ctxt = std::make_shared<CreateCalendarContext>();
49 auto input = [env, ctxt](size_t argc, napi_value* argv) {
50 // required 1 arguments :: <CalendarAccount>
51 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
52 NapiUtil::GetValue(env, argv[0], ctxt->account);
53 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
54 ctxt->ref = NapiUtil::NewWithRef(env, argc, argv, reinterpret_cast<void**>(&ctxt->calendar),
55 CalendarNapi::Constructor(env));
56 };
57 ctxt->GetCbInfo(env, info, input);
58
59 auto execute = [ctxt]() {
60 auto nativteCalendar = Native::CalendarManager::GetInstance().CreateCalendar(ctxt->account);
61 ctxt->status = (nativteCalendar != nullptr) ? napi_ok : napi_generic_failure;
62 CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar failed!");
63 ctxt->calendar->SetNative(nativteCalendar);
64 ctxt->id = nativteCalendar->GetId();
65 };
66 auto output = [env, ctxt](napi_value& result) {
67 ctxt->status = napi_get_reference_value(env, ctxt->ref, &result);
68 CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar output get ref value failed");
69 ctxt->status = NapiUtil::SetNamedProperty(env, "id", ctxt->id, result);
70 CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar SetNamedProperty id failed");
71 ctxt->status = napi_delete_reference(env, ctxt->ref);
72 CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar output del ref failed");
73 };
74 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
75 }
76
DeleteCalendar(napi_env env,napi_callback_info info)77 napi_value CalendarManagerNapi::DeleteCalendar(napi_env env, napi_callback_info info)
78 {
79 LOG_INFO("napi DeleteCalendar called");
80 struct DelCalendarContext : public ContextBase {
81 CalendarAccount account;
82 CalendarNapi *calendar;
83 bool delResult = false;
84 };
85 auto ctxt = std::make_shared<DelCalendarContext>();
86 auto input = [env, ctxt](size_t argc, napi_value* argv) {
87 // required 1 arguments :: <Calendar>
88 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
89 napi_valuetype type = napi_undefined;
90 napi_typeof(env, argv[0], &type);
91 CHECK_ARGS_RETURN_VOID(ctxt, type == napi_object, "type error!");
92 ctxt->status = CalendarNapi::ToJson(env, argv[0], ctxt->calendar);
93 CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
94 };
95 ctxt->GetCbInfo(env, info, input);
96
97 auto execute = [ctxt]() {
98 CHECK_RETURN_VOID(ctxt->calendar, "calendar is nullptr");
99 auto nativeCalendar = ctxt->calendar->GetNative();
100 CHECK_RETURN_VOID(nativeCalendar, "calendar is nullptr");
101 ctxt->delResult = Native::CalendarManager::GetInstance()
102 .DeleteCalendar(*(nativeCalendar.get()));
103 CHECK_RETURN_VOID(ctxt->delResult, "DeleteCalendar failed!");
104 };
105 auto output = [env, ctxt](napi_value& result) {
106 NapiUtil::SetValue(env, ctxt->delResult, result);
107 CHECK_STATUS_RETURN_VOID(ctxt, "output del ref failed");
108 };
109 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
110 }
111
112 struct GetCalendarContext : public ContextBase {
113 std::optional<CalendarAccount> account;
114 CalendarNapi *calendar = nullptr;
115 napi_ref ref = nullptr;
116 int id = -1;
117
GetCbInfoOHOS::CalendarApi::GetCalendarContext118 void GetCbInfo(napi_env env, napi_callback_info info)
119 {
120 auto input = [env, this](size_t argc, napi_value* argv) {
121 // required at least 1 arguments :: <CalendarAccount>
122 CHECK_ARGS_RETURN_VOID(this, argc <= 1, "invalid arguments!");
123 if (argc == 0) {
124 this->account = std::nullopt;
125 } else {
126 CalendarAccount tmpAccount;
127 NapiUtil::GetValue(env, argv[0], tmpAccount);
128 this->account = tmpAccount;
129 }
130 CHECK_STATUS_RETURN_VOID(this, "invalid arg[0], i.e. invalid keys!");
131 ref = NapiUtil::NewWithRef(env, argc, argv, reinterpret_cast<void**>(&calendar),
132 CalendarNapi::Constructor(env));
133 };
134 LOG_DEBUG("call ContextBase::GetCbInfo");
135 ContextBase::GetCbInfo(env, info, input);
136 }
137 };
138
GetCalendar(napi_env env,napi_callback_info info)139 napi_value CalendarManagerNapi::GetCalendar(napi_env env, napi_callback_info info)
140 {
141 LOG_DEBUG("GetCalendar in");
142 auto ctxt = std::make_shared<GetCalendarContext>();
143 ctxt->GetCbInfo(env, info);
144
145 auto execute = [ctxt]() {
146 auto nativteCalendar = Native::CalendarManager::GetInstance().GetCalendar(ctxt->account);
147 ctxt->status = (nativteCalendar != nullptr) ? napi_ok : napi_generic_failure;
148 CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar failed!");
149 ctxt->calendar->SetNative(nativteCalendar);
150 ctxt->id = nativteCalendar->GetId();
151 };
152 auto output = [env, ctxt](napi_value& result) {
153 ctxt->status = napi_get_reference_value(env, ctxt->ref, &result);
154 CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar output get ref value failed");
155 ctxt->status = NapiUtil::SetNamedProperty(env, "id", ctxt->id, result);
156 CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar SetNamedProperty id failed");
157 ctxt->status = napi_delete_reference(env, ctxt->ref);
158 CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar output del ref failed");
159 };
160 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
161 }
162
GetAllCalendars(napi_env env,napi_callback_info info)163 napi_value CalendarManagerNapi::GetAllCalendars(napi_env env, napi_callback_info info)
164 {
165 LOG_DEBUG("napi GetAllCalendars called");
166 struct GetAllCalendarContext : public ContextBase {
167 napi_callback_info info;
168 std::vector<napi_ref> refs;
169 };
170
171 auto ctxt = std::make_shared<GetAllCalendarContext>();
172 auto input = [env, ctxt](size_t argc, napi_value* argv) {
173 CHECK_ARGS_RETURN_VOID(ctxt, argc == 0, "invalid arguments!");
174 auto nativteCalendars = Native::CalendarManager::GetInstance().GetAllCalendars();
175 for (auto &calendar : nativteCalendars) {
176 CalendarNapi *calendarNapi = nullptr;
177 auto ref = NapiUtil::NewWithRef(env, argc, argv, reinterpret_cast<void**>(&calendarNapi),
178 CalendarNapi::Constructor(env));
179 CHECK_RETURN_VOID(calendarNapi != nullptr, "new CalendarNapi failed!");
180 calendarNapi->SetNative(calendar);
181 napi_value value;
182 ctxt->status = napi_get_reference_value(env, ref, &value);
183 CHECK_STATUS_RETURN_VOID(ctxt, "napi_get_reference_value failed");
184 ctxt->status = NapiUtil::SetNamedProperty(env, "id", calendar->GetId(), value);
185 CHECK_STATUS_RETURN_VOID(ctxt, "SetNamedProperty id failed");
186 ctxt->refs.emplace_back(ref);
187 }
188 };
189 ctxt->GetCbInfo(env, info, input);
190
191 auto execute = [env, ctxt]()->void {
192 };
193
194 auto output = [env, ctxt](napi_value& result) {
195 ctxt->status = napi_create_array_with_length(env, ctxt->refs.size(), &result);
196 CHECK_STATUS_RETURN_VOID(ctxt, "create array failed!");
197 int index = 0;
198 for (auto& ref : ctxt->refs) {
199 napi_value value;
200 ctxt->status = napi_get_reference_value(env, ref, &value);
201 CHECK_STATUS_RETURN_VOID(ctxt, "get ref value failed!");
202 ctxt->status = napi_set_element(env, result, index++, value);
203 CHECK_STATUS_RETURN_VOID(ctxt, "napi_set_element failed!");
204 ctxt->status = napi_delete_reference(env, ref);
205 CHECK_STATUS_RETURN_VOID(ctxt, "napi_delete_reference failed!");
206 }
207 };
208 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
209 }
210
GetCalendarManager(napi_env env,napi_callback_info info)211 napi_value GetCalendarManager(napi_env env, napi_callback_info info)
212 {
213 LOG_INFO("napi GetCalendarManager called");
214 const int argsOne = 1;
215 napi_value result = nullptr;
216 napi_value cons = nullptr;
217 size_t requireArgc = argsOne;
218 size_t argc = argsOne;
219 napi_value args[argsOne] = {nullptr};
220 if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
221 return nullptr;
222 }
223
224 if (argc > requireArgc || napi_get_reference_value(env, g_constructorRef, &cons) != napi_ok) {
225 return nullptr;
226 }
227
228 if (napi_new_instance(env, cons, argsOne, args, &result) != napi_ok) {
229 return nullptr;
230 }
231 CalendarManagerNapi *calendarManager = nullptr;
232 if (napi_unwrap(env, result, (void **)&calendarManager) != napi_ok) {
233 LOG_ERROR("Faild to get fileAccessHelper");
234 return nullptr;
235 }
236
237 if (calendarManager == nullptr) {
238 LOG_ERROR("fileAccessHelper is nullptr");
239 return nullptr;
240 }
241 return result;
242 }
243
New(napi_env env,napi_callback_info info)244 napi_value CalendarManagerNapi::New(napi_env env, napi_callback_info info)
245 {
246 auto ctxt = std::make_shared<ContextBase>();
247 auto input = [env, ctxt](size_t argc, napi_value* argv) {
248 CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
249 CalendarEnvNapi::GetInstance().Init(env, argv[0]);
250 };
251 ctxt->GetCbInfoSync(env, info, input);
252 NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
253
254 auto calendarManager = new (std::nothrow) CalendarManagerNapi();
255 NAPI_ASSERT(env, calendarManager != nullptr, "no memory for calendarManager");
256 auto finalize = [](napi_env env, void *data, void *hint) {
257 CalendarManagerNapi *objectInfo = static_cast<CalendarManagerNapi *>(data);
258 if (objectInfo != nullptr) {
259 delete objectInfo;
260 objectInfo = nullptr;
261 }
262 };
263 if (napi_wrap(env, ctxt->self, calendarManager, finalize, nullptr, nullptr) != napi_ok) {
264 finalize(env, calendarManager, nullptr);
265 return nullptr;
266 }
267 return ctxt->self;
268 }
269
Init(napi_env env,napi_value exports)270 napi_value CalendarManagerNapi::Init(napi_env env, napi_value exports)
271 {
272 napi_property_descriptor properties[] = {
273 DECLARE_NAPI_FUNCTION("createCalendar", CreateCalendar),
274 DECLARE_NAPI_FUNCTION("deleteCalendar", DeleteCalendar),
275 DECLARE_NAPI_FUNCTION("getCalendar", GetCalendar),
276 DECLARE_NAPI_FUNCTION("getAllCalendars", GetAllCalendars),
277 };
278 napi_value cons = nullptr;
279 NAPI_CALL(env,
280 napi_define_class(env,
281 CALENDAR_MANAGER_CLASS_NAME.c_str(),
282 NAPI_AUTO_LENGTH,
283 New,
284 nullptr,
285 sizeof(properties) / sizeof(*properties),
286 properties,
287 &cons));
288 NAPI_CALL(env, napi_create_reference(env, cons, INITIAL_REFCOUNT, &g_constructorRef));
289 NAPI_CALL(env, napi_set_named_property(env, exports, CALENDAR_MANAGER_CLASS_NAME.c_str(), cons));
290
291 napi_property_descriptor export_properties[] = {
292 DECLARE_NAPI_FUNCTION("getCalendarManager", GetCalendarManager),
293 };
294 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(export_properties) / sizeof(export_properties[0]),
295 export_properties));
296 return exports;
297 }
298 }