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_window_extension_context.h"
17 #include "js_window_extension.h"
18
19 #include <js_runtime_utils.h>
20 #include <js_extension_context.h>
21
22 #include "napi_common_start_options.h"
23 #include "napi_common_want.h"
24 #include "service_extension_context.h"
25 #include "start_options.h"
26 #include "window_manager_hilog.h"
27
28 namespace OHOS {
29 namespace Rosen {
30 using namespace AbilityRuntime;
31
32 namespace {
33 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "JSWindowExtensionContext"};
34 std::shared_ptr<AppExecFwk::EventHandler> handler_;
35 constexpr int32_t MIN_ARG_COUNT = 2;
36 }
37
NapiGetUndefined(napi_env env)38 napi_value NapiGetUndefined(napi_env env)
39 {
40 napi_value result = nullptr;
41 napi_get_undefined(env, &result);
42 return result;
43 }
44
45 class JsWindowExtensionContext final {
46 public:
JsWindowExtensionContext(const std::shared_ptr<WindowExtensionContext> & context)47 explicit JsWindowExtensionContext(
48 const std::shared_ptr<WindowExtensionContext>& context) : context_(context) {}
49 ~JsWindowExtensionContext() = default;
50
Finalizer(napi_env env,void * data,void * hint)51 static void Finalizer(napi_env env, void* data, void* hint)
52 {
53 WLOGI("JsWindowExtensionContext::Finalizer is called");
54 std::unique_ptr<JsWindowExtensionContext>(static_cast<JsWindowExtensionContext*>(data));
55 }
56
StartAbility(napi_env env,napi_callback_info info)57 static napi_value StartAbility(napi_env env, napi_callback_info info)
58 {
59 JsWindowExtensionContext* me = CheckParamsAndGetThis<JsWindowExtensionContext>(env, info);
60 return (me != nullptr) ? me->OnStartAbility(env, info) : nullptr;
61 }
62 private:
63 std::weak_ptr<WindowExtensionContext> context_;
64
CheckStartAbilityInputParam(napi_env env,napi_callback_info info,AAFwk::Want & want,AAFwk::StartOptions & startOptions) const65 bool CheckStartAbilityInputParam(
66 napi_env env, napi_callback_info info,
67 AAFwk::Want& want, AAFwk::StartOptions& startOptions) const
68 {
69 size_t argc = 2; // 2 : max param number
70 napi_value argv[2] = {nullptr}; // 2 : max param number
71 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
72 if (argc < 1) {
73 return false;
74 }
75 // Check input want
76 if (!CheckWantParam(env, argv[0], want)) {
77 return false;
78 }
79 if (argc > 1 && GetType(env, argv[1]) == napi_object) {
80 WLOGI("OnStartAbility start options is used.");
81 AppExecFwk::UnwrapStartOptions(env, argv[1], startOptions);
82 }
83 return true;
84 }
85
CheckWantParam(napi_env env,napi_value value,AAFwk::Want & want) const86 bool CheckWantParam(napi_env env, napi_value value, AAFwk::Want& want) const
87 {
88 if (!OHOS::AppExecFwk::UnwrapWant(env, value, want)) {
89 WLOGFE("The input want is invalid.");
90 return false;
91 }
92 WLOGI("UnwrapWant, BundleName: %{public}s, AbilityName: %{public}s.",
93 want.GetBundle().c_str(),
94 want.GetElement().GetAbilityName().c_str());
95 return true;
96 }
97
OnStartAbility(napi_env env,napi_callback_info info)98 napi_value OnStartAbility(napi_env env, napi_callback_info info)
99 {
100 WLOGI("OnStartAbility is called");
101 size_t argc = 4;
102 napi_value argv[4] = {nullptr};
103 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
104 if (argc < MIN_ARG_COUNT) { // at least two argc
105 WLOGFE("Start ability failed, not enough params.");
106 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_INVALID_PARAM)));
107 return NapiGetUndefined(env);
108 }
109
110 AAFwk::Want want;
111 AAFwk::StartOptions startOptions;
112 if (!CheckStartAbilityInputParam(env, info, want, startOptions)) {
113 napi_throw(env, CreateJsError(env, static_cast<int32_t>(WmErrorCode::WM_ERROR_INVALID_PARAM)));
114 return NapiGetUndefined(env);
115 }
116
117 NapiAsyncTask::CompleteCallback complete =
118 [weak = context_, want, startOptions](napi_env env, NapiAsyncTask& task, int32_t status) {
119 WLOGI("startAbility begin");
120 auto context = weak.lock();
121 if (!context) {
122 WLOGFW("context is released");
123 task.Reject(env, CreateJsError(env,
124 static_cast<int32_t>(WmErrorCode::WM_ERROR_STATE_ABNORMALLY)));
125 return;
126 }
127
128 WmErrorCode ret = WM_JS_TO_ERROR_CODE_MAP.at(context->StartAbility(want, startOptions));
129 if (ret == WmErrorCode::WM_OK) {
130 task.Resolve(env, NapiGetUndefined(env));
131 } else {
132 task.Reject(env, CreateJsError(env, static_cast<int32_t>(ret)));
133 }
134 };
135
136 napi_value lastParam = (argc <= 2) ? nullptr : argv[2]; // at least two argc
137 napi_value result = nullptr;
138 NapiAsyncTask::Schedule("JSServiceExtensionContext::OnStartAbility",
139 env, CreateAsyncTaskWithLastParam(env, lastParam, nullptr, std::move(complete), &result));
140 return result;
141 }
142 };
143
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int resultCode)144 void JsWindowConnectCallback::OnAbilityConnectDone(const AppExecFwk::ElementName& element,
145 const sptr<IRemoteObject>& remoteObject, int resultCode)
146 {
147 WLOGI("called");
148 }
149
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int resultCode)150 void JsWindowConnectCallback::OnAbilityDisconnectDone(const AppExecFwk::ElementName& element, int resultCode)
151 {
152 WLOGI("called");
153 }
154
CreateJsWindowExtensionContext(napi_env env,const std::shared_ptr<WindowExtensionContext> & context)155 napi_value CreateJsWindowExtensionContext(napi_env env, const std::shared_ptr<WindowExtensionContext>& context)
156 {
157 WLOGI("CreateJsWindowExtensionContext begin");
158 napi_value objValue = CreateJsExtensionContext(env, context);
159
160 std::unique_ptr<JsWindowExtensionContext> jsContext
161 = std::make_unique<JsWindowExtensionContext>(context);
162 napi_wrap(env, objValue, jsContext.release(), JsWindowExtensionContext::Finalizer, nullptr, nullptr);
163
164 // make handler
165 handler_ = std::make_shared<AppExecFwk::EventHandler>(AppExecFwk::EventRunner::GetMainEventRunner());
166
167 const char *moduleName = "JsWindowExtensionContext";
168 BindNativeFunction(env, objValue, "startAbility", moduleName, JsWindowExtensionContext::StartAbility);
169
170 return objValue;
171 }
172 } // namespace Rosen
173 } // namespace OHOS