• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 using namespace OHOS::AppExecFwk;
20 using namespace OHOS::DataShare;
21 static const int INVALID_EVENT_ID = -1;
22 static const int ARGS_INDEX_ONE = 1;
23 static const int ARGS_INDEX_TWO = 2;
24 static const int ARGS_INDEX_THREE = 3;
25 
26 namespace {
27     const std::string CALENDAR_MANAGER_CLASS_NAME = "CalendarManager";
28     static thread_local napi_ref g_constructorRef = nullptr;
29     constexpr uint32_t INITIAL_REFCOUNT = 1;
30 }
31 namespace OHOS::CalendarApi {
CreateCalendar(napi_env env,napi_callback_info info)32 napi_value CalendarManagerNapi::CreateCalendar(napi_env env, napi_callback_info info)
33 {
34     LOG_INFO("napi CreateCalendar called");
35     struct CreateCalendarContext : public ContextBase {
36         CalendarAccount account;
37         CalendarNapi *calendar;
38         int id;
39         napi_ref ref = nullptr;
40     };
41     auto ctxt = std::make_shared<CreateCalendarContext>();
42     auto input = [env, ctxt](size_t argc, napi_value* argv) {
43         // required 1 arguments :: <CalendarAccount>
44         CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
45         NapiUtil::GetValue(env, argv[0], ctxt->account);
46         CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
47         ctxt->ref = NapiUtil::NewWithRef(env, argc, argv, reinterpret_cast<void**>(&ctxt->calendar),
48             CalendarNapi::Constructor(env));
49     };
50     ctxt->GetCbInfo(env, info, input);
51 
52     auto execute = [ctxt]() {
53         auto nativteCalendar = Native::CalendarManager::GetInstance().CreateCalendar(ctxt->account);
54         ctxt->status = (nativteCalendar != nullptr) ? napi_ok : napi_generic_failure;
55         CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar failed!");
56         ctxt->calendar->SetNative(nativteCalendar);
57         ctxt->id = nativteCalendar->GetId();
58     };
59     auto output = [env, ctxt](napi_value& result) {
60         ctxt->status = napi_get_reference_value(env, ctxt->ref, &result);
61         CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar output get ref value failed");
62         ctxt->status = NapiUtil::SetNamedProperty(env, "id", ctxt->id, result);
63         CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar SetNamedProperty id failed");
64         ctxt->status = napi_delete_reference(env, ctxt->ref);
65         CHECK_STATUS_RETURN_VOID(ctxt, "CreateCalendar output del ref failed");
66     };
67     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
68 }
69 
DeleteCalendar(napi_env env,napi_callback_info info)70 napi_value CalendarManagerNapi::DeleteCalendar(napi_env env, napi_callback_info info)
71 {
72     LOG_INFO("napi DeleteCalendar called");
73     struct DelCalendarContext : public ContextBase {
74         CalendarAccount account;
75         CalendarNapi *calendar;
76         bool delResult = false;
77     };
78     auto ctxt = std::make_shared<DelCalendarContext>();
79     auto input = [env, ctxt](size_t argc, napi_value* argv) {
80         // required 1 arguments :: <Calendar>
81         CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
82         napi_valuetype type = napi_undefined;
83         napi_typeof(env, argv[0], &type);
84         CHECK_ARGS_RETURN_VOID(ctxt, type == napi_object, "type error!");
85         ctxt->status = CalendarNapi::ToJson(env, argv[0], ctxt->calendar);
86         CHECK_STATUS_RETURN_VOID(ctxt, "invalid arg[0], i.e. invalid keys!");
87     };
88     ctxt->GetCbInfo(env, info, input);
89 
90     auto execute = [ctxt]() {
91         CHECK_RETURN_VOID(ctxt->calendar, "calendar is nullptr");
92         auto nativeCalendar = ctxt->calendar->GetNative();
93         CHECK_RETURN_VOID(nativeCalendar, "calendar is nullptr");
94         ctxt->delResult = Native::CalendarManager::GetInstance()
95             .DeleteCalendar(*(nativeCalendar.get()));
96         CHECK_RETURN_VOID(ctxt->delResult, "DeleteCalendar failed!");
97     };
98     auto output = [env, ctxt](napi_value& result) {
99         NapiUtil::SetValue(env, ctxt->delResult, result);
100         CHECK_STATUS_RETURN_VOID(ctxt, "output del ref failed");
101     };
102     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
103 }
104 
105 struct GetCalendarContext : public ContextBase {
106     std::optional<CalendarAccount> account;
107     CalendarNapi *calendar = nullptr;
108     napi_ref ref = nullptr;
109     int id = -1;
110 
GetCbInfoOHOS::CalendarApi::GetCalendarContext111     void GetCbInfo(napi_env env, napi_callback_info info)
112     {
113         auto input = [env, this](size_t argc, napi_value* argv) {
114             // required at least 1 arguments :: <CalendarAccount>
115             CHECK_ARGS_RETURN_VOID(this, argc <= 1, "invalid arguments!");
116             if (argc == 0) {
117                 this->account = std::nullopt;
118             } else {
119                 CalendarAccount tmpAccount;
120                 NapiUtil::GetValue(env, argv[0], tmpAccount);
121                 this->account = tmpAccount;
122             }
123             CHECK_STATUS_RETURN_VOID(this, "invalid arg[0], i.e. invalid keys!");
124             ref = NapiUtil::NewWithRef(env, argc, argv, reinterpret_cast<void**>(&calendar),
125                 CalendarNapi::Constructor(env));
126         };
127         LOG_DEBUG("call ContextBase::GetCbInfo");
128         ContextBase::GetCbInfo(env, info, input);
129     }
130 };
131 
GetCalendar(napi_env env,napi_callback_info info)132 napi_value CalendarManagerNapi::GetCalendar(napi_env env, napi_callback_info info)
133 {
134     LOG_DEBUG("GetCalendar in");
135     auto ctxt = std::make_shared<GetCalendarContext>();
136     ctxt->GetCbInfo(env, info);
137 
138     auto execute = [ctxt]() {
139         auto nativteCalendar = Native::CalendarManager::GetInstance().GetCalendar(ctxt->account);
140         ctxt->status = (nativteCalendar != nullptr) ? napi_ok : napi_generic_failure;
141         CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar error!");
142         if (nativteCalendar->GetId() == -1) {
143             ctxt->status = napi_generic_failure;
144             CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar failed!");
145         }
146         if (ctxt->calendar != nullptr) {
147             ctxt->calendar->SetNative(nativteCalendar);
148         }
149         ctxt->id = nativteCalendar->GetId();
150     };
151     auto output = [env, ctxt](napi_value& result) {
152         ctxt->status = napi_get_reference_value(env, ctxt->ref, &result);
153         CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar output get ref value failed");
154         ctxt->status = NapiUtil::SetNamedProperty(env, "id", ctxt->id, result);
155         CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar SetNamedProperty id failed");
156         ctxt->status = napi_delete_reference(env, ctxt->ref);
157         CHECK_STATUS_RETURN_VOID(ctxt, "GetCalendar output del ref failed");
158     };
159     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
160 }
161 
GetAllCalendars(napi_env env,napi_callback_info info)162 napi_value CalendarManagerNapi::GetAllCalendars(napi_env env, napi_callback_info info)
163 {
164     LOG_DEBUG("napi GetAllCalendars called");
165     struct GetAllCalendarContext : public ContextBase {
166         napi_callback_info info;
167         std::vector<napi_ref> refs;
168     };
169 
170     auto ctxt = std::make_shared<GetAllCalendarContext>();
171     auto input = [env, ctxt](size_t argc, napi_value* argv) {
172         CHECK_ARGS_RETURN_VOID(ctxt, argc == 0, "invalid arguments!");
173         auto nativteCalendars = Native::CalendarManager::GetInstance().GetAllCalendars();
174         for (auto &calendar : nativteCalendars) {
175             CalendarNapi *calendarNapi = nullptr;
176             auto ref = NapiUtil::NewWithRef(env, argc, argv, reinterpret_cast<void**>(&calendarNapi),
177                 CalendarNapi::Constructor(env));
178             CHECK_RETURN_VOID(calendarNapi != nullptr, "new CalendarNapi failed!");
179             calendarNapi->SetNative(calendar);
180             napi_value value;
181             ctxt->status = napi_get_reference_value(env, ref, &value);
182             CHECK_STATUS_RETURN_VOID(ctxt, "napi_get_reference_value failed");
183             ctxt->status = NapiUtil::SetNamedProperty(env, "id", calendar->GetId(), value);
184             CHECK_STATUS_RETURN_VOID(ctxt, "SetNamedProperty id failed");
185             ctxt->refs.emplace_back(ref);
186         }
187     };
188     ctxt->GetCbInfo(env, info, input);
189 
190     auto execute = [env, ctxt]()->void {
191     };
192 
193     auto output = [env, ctxt](napi_value& result) {
194         ctxt->status = napi_create_array_with_length(env, ctxt->refs.size(), &result);
195         CHECK_STATUS_RETURN_VOID(ctxt, "create array failed!");
196         int index = 0;
197         for (auto& ref : ctxt->refs) {
198             napi_value value;
199             ctxt->status = napi_get_reference_value(env, ref, &value);
200             CHECK_STATUS_RETURN_VOID(ctxt, "get ref value failed!");
201             ctxt->status = napi_set_element(env, result, index++, value);
202             CHECK_STATUS_RETURN_VOID(ctxt, "napi_set_element failed!");
203             ctxt->status = napi_delete_reference(env, ref);
204             CHECK_STATUS_RETURN_VOID(ctxt, "napi_delete_reference failed!");
205         }
206     };
207     return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
208 }
209 
GetCalendarManager(napi_env env,napi_callback_info info)210 napi_value GetCalendarManager(napi_env env, napi_callback_info info)
211 {
212     LOG_INFO("napi GetCalendarManager called");
213     const int argsOne = 1;
214     napi_value result = nullptr;
215     napi_value cons = nullptr;
216     size_t requireArgc = argsOne;
217     size_t argc = argsOne;
218     napi_value args[argsOne] = {nullptr};
219     if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
220         return nullptr;
221     }
222 
223     if (argc > requireArgc || napi_get_reference_value(env, g_constructorRef, &cons) != napi_ok) {
224         return nullptr;
225     }
226 
227     if (napi_new_instance(env, cons, argsOne, args, &result) != napi_ok) {
228         return nullptr;
229     }
230     CalendarManagerNapi *calendarManager = nullptr;
231     if (napi_unwrap(env, result, (void **)&calendarManager) != napi_ok) {
232         LOG_ERROR("Faild to get fileAccessHelper");
233         return nullptr;
234     }
235 
236     if (calendarManager == nullptr) {
237         LOG_ERROR("fileAccessHelper is nullptr");
238         return nullptr;
239     }
240     return result;
241 }
242 
EditEvent(napi_env env,napi_callback_info info)243 napi_value CalendarManagerNapi::EditEvent(napi_env env, napi_callback_info info)
244 {
245     LOG_INFO("editEvent called");
246     napi_value eventId = nullptr;
247     NapiUtil::SetValue(env, INVALID_EVENT_ID, eventId);
248     auto ctxt = std::make_shared<EditEventContext>();
249     auto input = [env, ctxt](size_t argc, napi_value* argv) {
250         CHECK_ARGS_RETURN_VOID(ctxt, argc == ARGS_INDEX_THREE, "invalid arguments!");
251         ctxt-> _jsContext = argv[0];
252         NapiUtil::GetValue(env, argv[ARGS_INDEX_ONE], ctxt->event);
253         NapiUtil::GetValue(env, argv[ARGS_INDEX_TWO], ctxt->caller);
254     };
255     ctxt->GetCbInfo(env, info, input, true);
256 
257     bool isStageMode = false;
258     auto jsContext = ctxt->_jsContext;
259     auto status = OHOS::AbilityRuntime::IsStageContext(env, jsContext, isStageMode);
260     if (status != napi_ok || !isStageMode) {
261         LOG_ERROR("editEvent No support FA Model");
262         return eventId;
263     }
264     auto stageContext = OHOS::AbilityRuntime::GetStageModeContext(env, jsContext);
265     if (stageContext == nullptr) {
266         LOG_ERROR("editEvent stageContext == nullptr.");
267         return eventId;
268     }
269     auto abilityContext = OHOS::AbilityRuntime::Context::ConvertTo<AbilityRuntime::AbilityContext>(stageContext);
270     if (abilityContext == nullptr) {
271         LOG_ERROR("editEvent only support for UIAbility Context.");
272         return eventId;
273     }
274     ctxt->_uiContent = abilityContext->GetUIContent();
275     return LaunchEditorPage(env, ctxt);
276 }
277 
LaunchEditorPage(napi_env env,std::shared_ptr<EditEventContext> ctxt)278 napi_value CalendarManagerNapi::LaunchEditorPage(napi_env env, std::shared_ptr<EditEventContext> ctxt)
279 {
280     napi_value promise = nullptr;
281     napi_deferred deferred = nullptr;
282     napi_create_promise(env, &deferred, &promise);
283     AAFwk::Want want;
284     want.SetElementName("com.ohos.calendardata", "EditorUIExtensionAbility");
285     const std::string uiExtType = "sys/commonUI";
286     want.SetParam("ability.want.params.uiExtensionType", uiExtType);
287     want.SetParam("event", ctxt->event);
288     want.SetParam("caller", ctxt->caller);
289     Ace::ModalUIExtensionCallbacks callbacks;
290     callbacks = {
291         .onRelease = [env, ctxt, deferred](int32_t code) {
292             LOG_INFO("editEvent onRelease callback.");
293             ctxt->_uiContent->CloseModalUIExtension(ctxt->_sessionId);
294             napi_resolve_deferred(env, deferred, ctxt->id);
295             LOG_INFO("editEvent onRelease done.");
296         },
297         .onResult = [env, ctxt, deferred](int32_t code, const AAFwk::Want &wantRes) {
298             auto eventId = wantRes.GetIntParam("eventId", INVALID_EVENT_ID);
299             LOG_INFO("editEvent onResult. eventId=%{public}d", eventId);
300             NapiUtil::SetValue(env, eventId, ctxt->id);
301         },
302         .onReceive = [env, ctxt](const AAFwk::WantParams &wantParams) {
303             LOG_INFO("editEvent onReceive.");
304         },
305         .onError = [env, ctxt, deferred](int32_t code, const std::string &event, const std::string &msg) {
306             LOG_ERROR("editEvent onError.%{public}s", msg.c_str());
307             ctxt->_uiContent->CloseModalUIExtension(ctxt->_sessionId);
308             napi_reject_deferred(env, deferred, ctxt->id);
309         },
310         .onRemoteReady = [env, ctxt, deferred](const std::shared_ptr<Ace::ModalUIExtensionProxy> &proxy) {
311             LOG_INFO("editEvent onRemoteReady.");
312         },
313         .onDestroy = [env, ctxt, deferred]{
314             LOG_INFO("editEvent onDestroy.");
315         },
316     };
317     Ace::ModalUIExtensionConfig config;
318     config = {
319         .isProhibitBack = false,
320     };
321     ctxt->_sessionId = ctxt->_uiContent->CreateModalUIExtension(want, callbacks, config);
322     LOG_INFO("editEvent CreateModalUI sessionId=%{public}d", ctxt->_sessionId);
323     return promise;
324 }
325 
New(napi_env env,napi_callback_info info)326 napi_value CalendarManagerNapi::New(napi_env env, napi_callback_info info)
327 {
328     auto ctxt = std::make_shared<ContextBase>();
329     auto input = [env, ctxt](size_t argc, napi_value* argv) {
330         CHECK_ARGS_RETURN_VOID(ctxt, argc == 1, "invalid arguments!");
331         CalendarEnvNapi::GetInstance().Init(env, argv[0]);
332     };
333     ctxt->GetCbInfoSync(env, info, input);
334     NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!");
335 
336     auto calendarManager = new (std::nothrow) CalendarManagerNapi();
337     NAPI_ASSERT(env, calendarManager != nullptr, "no memory for calendarManager");
338     auto finalize = [](napi_env env, void *data, void *hint) {
339         CalendarManagerNapi *objectInfo = static_cast<CalendarManagerNapi *>(data);
340         if (objectInfo != nullptr) {
341             delete objectInfo;
342             objectInfo = nullptr;
343         }
344     };
345     if (napi_wrap(env, ctxt->self, calendarManager, finalize, nullptr, nullptr) != napi_ok) {
346         finalize(env, calendarManager, nullptr);
347         return nullptr;
348     }
349     return ctxt->self;
350 }
351 
Init(napi_env env,napi_value exports)352 napi_value CalendarManagerNapi::Init(napi_env env, napi_value exports)
353 {
354     napi_property_descriptor properties[] = {
355         DECLARE_NAPI_FUNCTION("createCalendar", CreateCalendar),
356         DECLARE_NAPI_FUNCTION("deleteCalendar", DeleteCalendar),
357         DECLARE_NAPI_FUNCTION("getCalendar", GetCalendar),
358         DECLARE_NAPI_FUNCTION("getAllCalendars", GetAllCalendars),
359         DECLARE_NAPI_FUNCTION("editEvent", EditEvent),
360     };
361     napi_value cons = nullptr;
362     NAPI_CALL(env,
363         napi_define_class(env,
364             CALENDAR_MANAGER_CLASS_NAME.c_str(),
365             NAPI_AUTO_LENGTH,
366             New,
367             nullptr,
368             sizeof(properties) / sizeof(*properties),
369             properties,
370             &cons));
371     NAPI_CALL(env, napi_create_reference(env, cons, INITIAL_REFCOUNT, &g_constructorRef));
372     NAPI_CALL(env, napi_set_named_property(env, exports, CALENDAR_MANAGER_CLASS_NAME.c_str(), cons));
373 
374     napi_property_descriptor export_properties[] = {
375         DECLARE_NAPI_FUNCTION("getCalendarManager", GetCalendarManager),
376     };
377     NAPI_CALL(env, napi_define_properties(env, exports, sizeof(export_properties) / sizeof(export_properties[0]),
378         export_properties));
379     return exports;
380 }
381 }