• 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 "js_media_control_extension_context.h"
17 
18 #include <cstdint>
19 
20 #include "event_handler.h"
21 #include "hilog_wrapper.h"
22 #include "js_extension_context.h"
23 #include "js_error_utils.h"
24 #include "js_data_struct_converter.h"
25 #include "js_runtime.h"
26 #include "js_runtime_utils.h"
27 #include "napi/native_api.h"
28 #include "napi_common_ability.h"
29 #include "napi_common_want.h"
30 #include "napi_common_util.h"
31 #include "napi_common_start_options.h"
32 #include "start_options.h"
33 #include "hitrace_meter.h"
34 
35 namespace OHOS {
36 namespace AbilityRuntime {
37 namespace {
38 constexpr int32_t INDEX_ZERO = 0;
39 constexpr int32_t ERROR_CODE_ONE = 1;
40 constexpr size_t ARGC_ZERO = 0;
41 constexpr size_t ARGC_ONE = 1;
42 } // namespace
43 
44 static std::shared_ptr<AppExecFwk::EventHandler> handler_ = nullptr;
45 
Finalizer(NativeEngine * engine,void * data,void * hint)46 void JsMediaControlExtensionContext::Finalizer(NativeEngine* engine, void* data, void* hint)
47 {
48     HILOG_DEBUG("JsMediaControlExtensionContext Finalizer is called");
49     std::unique_ptr<JsMediaControlExtensionContext>(static_cast<JsMediaControlExtensionContext*>(data));
50 }
51 
StartAbility(NativeEngine * engine,NativeCallbackInfo * info)52 NativeValue *JsMediaControlExtensionContext::StartAbility(NativeEngine* engine, NativeCallbackInfo* info)
53 {
54     JsMediaControlExtensionContext* me = CheckParamsAndGetThis<JsMediaControlExtensionContext>(engine, info);
55     return (me != nullptr) ? me->OnStartAbility(*engine, *info) : nullptr;
56 }
57 
TerminateSelf(NativeEngine * engine,NativeCallbackInfo * info)58 NativeValue *JsMediaControlExtensionContext::TerminateSelf(NativeEngine* engine, NativeCallbackInfo* info)
59 {
60     JsMediaControlExtensionContext* me = CheckParamsAndGetThis<JsMediaControlExtensionContext>(engine, info);
61     return (me != nullptr) ? me->OnTerminateSelf(*engine, *info) : nullptr;
62 }
63 
TerminateSelfWithResult(NativeEngine * engine,NativeCallbackInfo * info)64 NativeValue* JsMediaControlExtensionContext::TerminateSelfWithResult(NativeEngine* engine, NativeCallbackInfo* info)
65 {
66     JsMediaControlExtensionContext* me = CheckParamsAndGetThis<JsMediaControlExtensionContext>(engine, info);
67     return (me != nullptr) ? me->OnTerminateSelfWithResult(*engine, *info) : nullptr;
68 }
69 
OnStartAbility(NativeEngine & engine,NativeCallbackInfo & info)70 NativeValue *JsMediaControlExtensionContext::OnStartAbility(NativeEngine& engine, NativeCallbackInfo& info)
71 {
72     HITRACE_METER_NAME(HITRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
73     HILOG_DEBUG("OnStartAbility is called");
74     if (info.argc < ARGC_ONE) {
75         HILOG_ERROR("Start ability failed, not enough params.");
76         ThrowTooFewParametersError(engine);
77         return engine.CreateUndefined();
78     }
79 
80     size_t unwrapArgc = 0;
81     AAFwk::Want want;
82     AAFwk::StartOptions startOptions;
83     if (!CheckStartAbilityInputParam(engine, info, want, startOptions, unwrapArgc)) {
84         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
85         return engine.CreateUndefined();
86     }
87 
88     AsyncTask::CompleteCallback complete =
89         [weak = context_, want, startOptions, unwrapArgc](NativeEngine& engine, AsyncTask& task, int32_t status) {
90             HILOG_DEBUG("startAbility begin");
91             auto context = weak.lock();
92             if (!context) {
93                 HILOG_ERROR("context is released");
94                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
95                 return;
96             }
97 
98             ErrCode innerErrorCode = ERR_OK;
99             (unwrapArgc == 1) ? innerErrorCode = context->StartAbility(want) :
100                 innerErrorCode = context->StartAbility(want, startOptions);
101             if (innerErrorCode == 0) {
102                 task.Resolve(engine, engine.CreateUndefined());
103             } else {
104                 task.Reject(engine, CreateJsErrorByNativeErr(engine, innerErrorCode));
105             }
106         };
107 
108     NativeValue* lastParam = (info.argc == unwrapArgc) ? nullptr : info.argv[unwrapArgc];
109     NativeValue* result = nullptr;
110     AsyncTask::Schedule("JSMediaControlExtensionContext OnStartAbility",
111         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
112     return result;
113 }
114 
OnTerminateSelf(NativeEngine & engine,const NativeCallbackInfo & info)115 NativeValue *JsMediaControlExtensionContext::OnTerminateSelf(NativeEngine& engine, const NativeCallbackInfo& info)
116 {
117     HILOG_DEBUG("OnTerminateSelf is called");
118     AsyncTask::CompleteCallback complete =
119         [weak = context_](NativeEngine& engine, AsyncTask& task, int32_t status) {
120             auto context = weak.lock();
121             if (!context) {
122                 HILOG_ERROR("context is released");
123                 task.Reject(engine, CreateJsError(engine, ERROR_CODE_ONE, "Context is released"));
124                 return;
125             }
126 
127             ErrCode innerErrorCode = context->TerminateSelf();
128             if (innerErrorCode == 0) {
129                 task.Resolve(engine, engine.CreateUndefined());
130             } else {
131                 task.Reject(engine, CreateJsErrorByNativeErr(engine, innerErrorCode));
132             }
133         };
134 
135     NativeValue* lastParam = (info.argc == ARGC_ZERO) ? nullptr : info.argv[INDEX_ZERO];
136     NativeValue* result = nullptr;
137     AsyncTask::Schedule("JSMediaControlExtensionContext OnTerminateSelf",
138         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
139     return result;
140 }
141 
OnTerminateSelfWithResult(NativeEngine & engine,const NativeCallbackInfo & info)142 NativeValue* JsMediaControlExtensionContext::OnTerminateSelfWithResult(NativeEngine& engine,
143     const NativeCallbackInfo& info)
144 {
145     HILOG_INFO("OnTerminateSelfWithResult is called");
146 
147     if (info.argc == 0) {
148         HILOG_ERROR("Not enough params");
149         ThrowTooFewParametersError(engine);
150         return engine.CreateUndefined();
151     }
152 
153     int resultCode = 0;
154     AAFwk::Want want;
155     if (!JsMediaControlExtensionContext::UnWrapAbilityResult(engine, info.argv[0], resultCode, want)) {
156         HILOG_ERROR("OnTerminateSelfWithResult Failed to parse ability result!");
157         ThrowError(engine, AbilityErrorCode::ERROR_CODE_INVALID_PARAM);
158         return engine.CreateUndefined();
159     }
160 
161     AsyncTask::CompleteCallback complete =
162         [weak = context_, want, resultCode](NativeEngine& engine, AsyncTask& task, int32_t status) {
163             auto context = weak.lock();
164             if (!context) {
165                 HILOG_WARN("context is released");
166                 task.Reject(engine, CreateJsError(engine, AbilityErrorCode::ERROR_CODE_INVALID_CONTEXT));
167                 return;
168             }
169 
170             auto errorCode = context->TerminateSelf();
171             if (errorCode == 0) {
172                 task.Resolve(engine, engine.CreateUndefined());
173             } else {
174                 task.Reject(engine, CreateJsErrorByNativeErr(engine, errorCode));
175             }
176         };
177 
178     NativeValue* lastParam = (info.argc > ARGC_ONE) ? info.argv[1] : nullptr;
179     NativeValue* result = nullptr;
180     AsyncTask::Schedule("JsMediaControlExtensionContext::OnTerminateSelfWithResult",
181         engine, CreateAsyncTaskWithLastParam(engine, lastParam, nullptr, std::move(complete), &result));
182     HILOG_INFO("OnTerminateSelfWithResult is called end");
183     return result;
184 }
185 
CreateJsMediaControlExtensionContext(NativeEngine & engine,std::shared_ptr<MediaControlExtensionContext> context)186 NativeValue *JsMediaControlExtensionContext::CreateJsMediaControlExtensionContext(NativeEngine& engine,
187     std::shared_ptr<MediaControlExtensionContext> context)
188 {
189     HILOG_DEBUG("CreateJsMediaControlExtensionContext begin");
190     std::shared_ptr<OHOS::AppExecFwk::AbilityInfo> abilityInfo = nullptr;
191     if (context) {
192         abilityInfo = context->GetAbilityInfo();
193     }
194     NativeValue* objValue = CreateJsExtensionContext(engine, context, abilityInfo);
195     NativeObject* object = ConvertNativeValueTo<NativeObject>(objValue);
196 
197     std::unique_ptr<JsMediaControlExtensionContext> jsContext =
198       std::make_unique<JsMediaControlExtensionContext>(context);
199     object->SetNativePointer(jsContext.release(), Finalizer, nullptr);
200 
201     // make handler
202     handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
203 
204     const char *moduleName = "JsMediaControlExtensionContext";
205     BindNativeFunction(engine, *object, "startAbility", moduleName, StartAbility);
206     BindNativeFunction(engine, *object, "terminateSelf", moduleName, TerminateSelf);
207     BindNativeFunction(engine, *object, "terminateSelfWithResult", moduleName, TerminateSelfWithResult);
208 
209     return objValue;
210 }
211 
CheckStartAbilityInputParam(NativeEngine & engine,NativeCallbackInfo & info,AAFwk::Want & want,AAFwk::StartOptions & startOptions,size_t & unwrapArgc) const212 bool JsMediaControlExtensionContext::CheckStartAbilityInputParam(NativeEngine& engine, NativeCallbackInfo& info,
213     AAFwk::Want& want, AAFwk::StartOptions& startOptions, size_t& unwrapArgc) const
214 {
215     if (info.argc < ARGC_ONE) {
216         return false;
217     }
218     unwrapArgc = ARGC_ZERO;
219 
220     // Check input want
221     if (!CheckWantParam(engine, info.argv[INDEX_ZERO], want)) {
222         return false;
223     }
224     ++unwrapArgc;
225     if (info.argc > ARGC_ONE && info.argv[1]->TypeOf() == NATIVE_OBJECT) {
226         AppExecFwk::UnwrapStartOptions(reinterpret_cast<napi_env>(&engine),
227             reinterpret_cast<napi_value>(info.argv[1]), startOptions);
228         unwrapArgc++;
229     }
230     return true;
231 }
232 
CheckWantParam(NativeEngine & engine,NativeValue * value,AAFwk::Want & want) const233 bool JsMediaControlExtensionContext::CheckWantParam(NativeEngine& engine, NativeValue* value, AAFwk::Want& want) const
234 {
235     if (!OHOS::AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine),
236         reinterpret_cast<napi_value>(value), want)) {
237         HILOG_ERROR("The input want is invalid.");
238         return false;
239     }
240     HILOG_DEBUG("UnwrapWant, BundleName: %{public}s, AbilityName: %{public}s.", want.GetBundle().c_str(),
241         want.GetElement().GetAbilityName().c_str());
242     return true;
243 }
244 
UnWrapWant(NativeEngine & engine,NativeValue * argv,AAFwk::Want & want)245 bool JsMediaControlExtensionContext::UnWrapWant(NativeEngine& engine, NativeValue* argv, AAFwk::Want& want)
246 {
247     if (argv == nullptr) {
248         HILOG_WARN("UnWrapWant argv == nullptr!");
249         return false;
250     }
251     return AppExecFwk::UnwrapWant(reinterpret_cast<napi_env>(&engine), reinterpret_cast<napi_value>(argv), want);
252 }
253 
UnWrapAbilityResult(NativeEngine & engine,NativeValue * argv,int & resultCode,AAFwk::Want & want)254 bool JsMediaControlExtensionContext::UnWrapAbilityResult(NativeEngine& engine, NativeValue* argv, int& resultCode,
255     AAFwk::Want& want)
256 {
257     if (argv == nullptr) {
258         HILOG_WARN("UnWrapAbilityResult argv == nullptr!");
259         return false;
260     }
261     if (argv->TypeOf() != NativeValueType::NATIVE_OBJECT) {
262         HILOG_WARN("UnWrapAbilityResult invalid type of abilityResult!");
263         return false;
264     }
265     NativeObject* jObj = ConvertNativeValueTo<NativeObject>(argv);
266     NativeValue* jResultCode = jObj->GetProperty("resultCode");
267     if (jResultCode == nullptr) {
268         HILOG_WARN("UnWrapAbilityResult jResultCode == nullptr!");
269         return false;
270     }
271     if (jResultCode->TypeOf() != NativeValueType::NATIVE_NUMBER) {
272         HILOG_WARN("UnWrapAbilityResult invalid type of resultCode!");
273         return false;
274     }
275     resultCode = int64_t(*ConvertNativeValueTo<NativeNumber>(jObj->GetProperty("resultCode")));
276     NativeValue* jWant = jObj->GetProperty("want");
277     if (jWant == nullptr) {
278         HILOG_WARN("UnWrapAbilityResult jWant == nullptr!");
279         return false;
280     }
281     if (jWant->TypeOf() != NativeValueType::NATIVE_OBJECT) {
282         HILOG_WARN("UnWrapAbilityResult invalid type of want!");
283         return false;
284     }
285     return JsMediaControlExtensionContext::UnWrapWant(engine, jWant, want);
286 }
287 }  // namespace AbilityRuntime
288 }  // namespace OHOS
289