1 /*
2 * Copyright (c) 2022 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_work_scheduler_extension_context.h"
17
18 #include "js_extension_context.h"
19 #include "js_runtime.h"
20 #include "js_runtime_utils.h"
21 #include "js_error_utils.h"
22 #include "napi/native_api.h"
23 #include "napi_common_want.h"
24 #include "napi_common_util.h"
25
26 namespace OHOS {
27 namespace WorkScheduler {
28 namespace {
29 using namespace OHOS::AbilityRuntime;
30 constexpr size_t ARGC_ONE = 1;
31 constexpr size_t INDEX_ZERO = 0;
32 class JsWorkSchedulerExtensionContext final {
33 public:
JsWorkSchedulerExtensionContext(const std::shared_ptr<WorkSchedulerExtensionContext> & context)34 explicit JsWorkSchedulerExtensionContext(const std::shared_ptr<WorkSchedulerExtensionContext>& context)
35 : context_(context) {}
36 ~JsWorkSchedulerExtensionContext() = default;
37
Finalizer(napi_env env,void * data,void * hint)38 static void Finalizer(napi_env env, void* data, void* hint)
39 {
40 std::unique_ptr<JsWorkSchedulerExtensionContext>(
41 static_cast<JsWorkSchedulerExtensionContext*>(data));
42 }
43
StartServiceExtensionAbility(napi_env env,napi_callback_info info)44 static napi_value StartServiceExtensionAbility(napi_env env, napi_callback_info info)
45 {
46 GET_NAPI_INFO_AND_CALL(env, info, JsWorkSchedulerExtensionContext, OnStartExtensionAbility);
47 }
48
StopServiceExtensionAbility(napi_env env,napi_callback_info info)49 static napi_value StopServiceExtensionAbility(napi_env env, napi_callback_info info)
50 {
51 GET_NAPI_INFO_AND_CALL(env, info, JsWorkSchedulerExtensionContext, OnStopExtensionAbility);
52 }
53
OnStartExtensionAbility(napi_env env,NapiCallbackInfo & info)54 napi_value OnStartExtensionAbility(napi_env env, NapiCallbackInfo& info)
55 {
56 WS_HILOGI("called");
57 if (info.argc < ARGC_ONE) {
58 WS_HILOGE("invalid argc");
59 ThrowTooFewParametersError(env);
60 return CreateJsUndefined(env);
61 }
62 AAFwk::Want want;
63 if (!AppExecFwk::UnwrapWant(env, info.argv[INDEX_ZERO], want)) {
64 ThrowInvalidParamError(env, "Parse param want failed, must be a Want.");
65 return CreateJsUndefined(env);
66 }
67 WS_HILOGI("%{public}s", want.ToString().c_str());
68 NapiAsyncTask::CompleteCallback complete =
69 [weak = context_, want](napi_env env, NapiAsyncTask& task, int32_t status) {
70 auto context = weak.lock();
71 if (!context) {
72 WS_HILOGE("context released");
73 task.Reject(env, CreateJsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
74 return;
75 }
76 auto innerErrorCode = context->StartServiceExtensionAbility(want);
77 if (innerErrorCode == 0) {
78 WS_HILOGI("OK");
79 task.Resolve(env, CreateJsUndefined(env));
80 } else {
81 WS_HILOGE("failed");
82 task.Reject(env, CreateJsErrorByNativeErr(env, innerErrorCode));
83 }
84 };
85
86 napi_value lastParam = (info.argc <= ARGC_ONE) ? nullptr : info.argv[ARGC_ONE];
87 napi_value result = nullptr;
88 NapiAsyncTask::ScheduleHighQos("JSWorkSchedulerExtensionContext::OnStartExtensionAbility",
89 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
90 return result;
91 }
92
OnStopExtensionAbility(napi_env env,NapiCallbackInfo & info)93 napi_value OnStopExtensionAbility(napi_env env, NapiCallbackInfo& info)
94 {
95 WS_HILOGI("called");
96 if (info.argc < ARGC_ONE) {
97 WS_HILOGE("invalid argc");
98 ThrowTooFewParametersError(env);
99 return CreateJsUndefined(env);
100 }
101 AAFwk::Want want;
102 if (!AppExecFwk::UnwrapWant(env, info.argv[INDEX_ZERO], want)) {
103 ThrowInvalidParamError(env, "Parse param want failed, must be a Want.");
104 return CreateJsUndefined(env);
105 }
106 WS_HILOGI("%{public}s", want.ToString().c_str());
107 NapiAsyncTask::CompleteCallback complete =
108 [weak = context_, want](napi_env env, NapiAsyncTask& task, int32_t status) {
109 auto context = weak.lock();
110 if (!context) {
111 WS_HILOGE("context released");
112 task.Reject(env, CreateJsError(env, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
113 return;
114 }
115 auto innerErrorCode = context->StopServiceExtensionAbility(want);
116 if (innerErrorCode == 0) {
117 task.Resolve(env, CreateJsUndefined(env));
118 } else {
119 task.Reject(env, CreateJsErrorByNativeErr(env, innerErrorCode));
120 }
121 };
122
123 napi_value lastParam = (info.argc <= ARGC_ONE) ? nullptr : info.argv[ARGC_ONE];
124 napi_value result = nullptr;
125 NapiAsyncTask::Schedule("JSWorkSchedulerExtensionContext::OnStopExtensionAbility",
126 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
127 return result;
128 }
129
130 private:
131 std::weak_ptr<WorkSchedulerExtensionContext> context_;
132 };
133 } // namespace
134
CreateJsWorkSchedulerExtensionContext(napi_env env,std::shared_ptr<WorkSchedulerExtensionContext> context)135 napi_value CreateJsWorkSchedulerExtensionContext(napi_env env,
136 std::shared_ptr<WorkSchedulerExtensionContext> context)
137 {
138 napi_value objValue = AbilityRuntime::CreateJsExtensionContext(env, context);
139
140 std::unique_ptr<JsWorkSchedulerExtensionContext> jsContext =
141 std::make_unique<JsWorkSchedulerExtensionContext>(context);
142 napi_status status = napi_wrap(env, objValue, jsContext.release(), JsWorkSchedulerExtensionContext::Finalizer,
143 nullptr, nullptr);
144 if (status != napi_ok) {
145 WS_HILOGE("JsWorkSchedulerExtensionContext failed to wrap the object");
146 return nullptr;
147 }
148 const char *moduleName = "JsWorkSchedulerExtensionContext";
149 BindNativeFunction(env, objValue, "startServiceExtensionAbility", moduleName,
150 JsWorkSchedulerExtensionContext::StartServiceExtensionAbility);
151 BindNativeFunction(env, objValue, "stopServiceExtensionAbility", moduleName,
152 JsWorkSchedulerExtensionContext::StopServiceExtensionAbility);
153 return objValue;
154 }
155 } // namespace WorkScheduler
156 } // namespace OHOS