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_static_subscriber_extension.h"
17
18 #include "ability_info.h"
19 #include "ability_handler.h"
20 #include "event_log_wrapper.h"
21 #include "js_runtime.h"
22 #include "js_runtime_utils.h"
23 #include "js_static_subscriber_extension_context.h"
24 #include "napi_common_want.h"
25 #include "napi/native_api.h"
26 #include "napi/native_node_api.h"
27 #include "napi_remote_object.h"
28 #include "static_subscriber_stub_impl.h"
29
30 namespace OHOS {
31 namespace EventFwk {
32 namespace {
33 constexpr size_t ARGC_ONE = 1;
34 }
35
36 using namespace OHOS::AppExecFwk;
37
AttachStaticSubscriberExtensionContext(napi_env env,void * value,void *)38 napi_value AttachStaticSubscriberExtensionContext(napi_env env, void* value, void*)
39 {
40 EVENT_LOGD("AttachStaticSubscriberExtensionContext");
41 if (value == nullptr) {
42 EVENT_LOGE("invalid parameter.");
43 return nullptr;
44 }
45
46 auto ptr = reinterpret_cast<std::weak_ptr<StaticSubscriberExtensionContext>*>(value)->lock();
47 if (ptr == nullptr) {
48 EVENT_LOGE("invalid context.");
49 return nullptr;
50 }
51
52 napi_value object = CreateJsStaticSubscriberExtensionContext(env, ptr);
53 auto napiContextObj = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(env,
54 "application.StaticSubscriberExtensionContext", &object, 1)->GetNapiValue();
55 napi_coerce_to_native_binding_object(env, napiContextObj, AbilityRuntime::DetachCallbackFunc,
56 AttachStaticSubscriberExtensionContext, value, nullptr);
57 auto workContext = new (std::nothrow) std::weak_ptr<StaticSubscriberExtensionContext>(ptr);
58
59 napi_wrap(env, napiContextObj, workContext,
60 [](napi_env, void* data, void*) {
61 EVENT_LOGI("Finalizer for weak_ptr static subscriber extension context is called");
62 delete static_cast<std::weak_ptr<StaticSubscriberExtensionContext>*>(data);
63 }, nullptr, nullptr);
64 return napiContextObj;
65 }
66
Create(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)67 JsStaticSubscriberExtension* JsStaticSubscriberExtension::Create(
68 const std::unique_ptr<AbilityRuntime::Runtime>& runtime)
69 {
70 return new (std::nothrow) JsStaticSubscriberExtension(static_cast<AbilityRuntime::JsRuntime&>(*runtime));
71 }
72
JsStaticSubscriberExtension(AbilityRuntime::JsRuntime & jsRuntime)73 JsStaticSubscriberExtension::JsStaticSubscriberExtension(AbilityRuntime::JsRuntime& jsRuntime)
74 : jsRuntime_(jsRuntime) {}
~JsStaticSubscriberExtension()75 JsStaticSubscriberExtension::~JsStaticSubscriberExtension()
76 {
77 EVENT_LOGD("Js static subscriber extension destructor.");
78 auto context = GetContext();
79 if (context) {
80 context->Unbind();
81 }
82
83 jsRuntime_.FreeNativeReference(std::move(jsObj_));
84 }
85
Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord> & record,const std::shared_ptr<AppExecFwk::OHOSApplication> & application,std::shared_ptr<AppExecFwk::AbilityHandler> & handler,const sptr<IRemoteObject> & token)86 void JsStaticSubscriberExtension::Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord>& record,
87 const std::shared_ptr<AppExecFwk::OHOSApplication>& application,
88 std::shared_ptr<AppExecFwk::AbilityHandler>& handler,
89 const sptr<IRemoteObject>& token)
90 {
91 StaticSubscriberExtension::Init(record, application, handler, token);
92 if (Extension::abilityInfo_->srcEntrance.empty()) {
93 EVENT_LOGE("srcEntrance of abilityInfo is empty");
94 return;
95 }
96
97 std::string srcPath(Extension::abilityInfo_->moduleName + "/");
98 srcPath.append(Extension::abilityInfo_->srcEntrance);
99 srcPath.erase(srcPath.rfind('.'));
100 srcPath.append(".abc");
101
102 std::string moduleName(Extension::abilityInfo_->moduleName);
103 moduleName.append("::").append(abilityInfo_->name);
104 EVENT_LOGD("moduleName: %{public}s, srcPath: %{public}s.", moduleName.c_str(), srcPath.c_str());
105 AbilityRuntime::HandleScope handleScope(jsRuntime_);
106 napi_env env = jsRuntime_.GetNapiEnv();
107
108 jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath,
109 abilityInfo_->compileMode == CompileMode::ES_MODULE);
110 if (jsObj_ == nullptr) {
111 EVENT_LOGE("Failed to load module");
112 return;
113 }
114 napi_value obj = jsObj_->GetNapiValue();
115 if (obj == nullptr) {
116 EVENT_LOGE("Failed to get static subscriber extension object");
117 return;
118 }
119
120 auto context = GetContext();
121 if (context == nullptr) {
122 EVENT_LOGE("Failed to get context");
123 return;
124 }
125
126 napi_value contextObj = CreateJsStaticSubscriberExtensionContext(env, context);
127 auto shellContextRef = AbilityRuntime::JsRuntime::LoadSystemModuleByEngine(
128 env, "application.StaticSubscriberExtensionContext", &contextObj, ARGC_ONE);
129 napi_value nativeObj = shellContextRef->GetNapiValue();
130 if (nativeObj == nullptr) {
131 EVENT_LOGE("Failed to get context native object");
132 return;
133 }
134
135 auto workContext = new (std::nothrow) std::weak_ptr<StaticSubscriberExtensionContext>(context);
136 napi_coerce_to_native_binding_object(env, nativeObj, AbilityRuntime::DetachCallbackFunc,
137 AttachStaticSubscriberExtensionContext, workContext, nullptr);
138 context->Bind(jsRuntime_, shellContextRef.release());
139 napi_set_named_property(env, obj, "context", nativeObj);
140
141 EVENT_LOGD("Set static subscriber extension context");
142 napi_wrap(env, nativeObj, workContext,
143 [](napi_env, void* data, void*) {
144 EVENT_LOGI("Finalizer for weak_ptr static subscriber extension context is called");
145 delete static_cast<std::weak_ptr<StaticSubscriberExtensionContext>*>(data);
146 }, nullptr, nullptr);
147
148 EVENT_LOGI("Init end.");
149 }
150
OnStart(const AAFwk::Want & want)151 void JsStaticSubscriberExtension::OnStart(const AAFwk::Want& want)
152 {
153 EVENT_LOGD("%{public}s called.", __func__);
154 Extension::OnStart(want);
155 }
156
OnStop()157 void JsStaticSubscriberExtension::OnStop()
158 {
159 EVENT_LOGD("%{public}s called.", __func__);
160 Extension::OnStop();
161 }
162
OnConnect(const AAFwk::Want & want)163 sptr<IRemoteObject> JsStaticSubscriberExtension::OnConnect(const AAFwk::Want& want)
164 {
165 EVENT_LOGD("%{public}s called.", __func__);
166 Extension::OnConnect(want);
167 sptr<StaticSubscriberStubImpl> remoteObject = new (std::nothrow) StaticSubscriberStubImpl(
168 std::static_pointer_cast<JsStaticSubscriberExtension>(shared_from_this()));
169 return remoteObject->AsObject();
170 }
171
OnDisconnect(const AAFwk::Want & want)172 void JsStaticSubscriberExtension::OnDisconnect(const AAFwk::Want& want)
173 {
174 EVENT_LOGD("%{public}s called.", __func__);
175 Extension::OnDisconnect(want);
176 }
177
OnReceiveEvent(std::shared_ptr<CommonEventData> data)178 void JsStaticSubscriberExtension::OnReceiveEvent(std::shared_ptr<CommonEventData> data)
179 {
180 EVENT_LOGD("%{public}s called.", __func__);
181 if (handler_ == nullptr) {
182 EVENT_LOGE("handler is invalid");
183 return;
184 }
185
186 auto task = [this, data]() {
187 if (data == nullptr) {
188 EVENT_LOGE("OnReceiveEvent common event data is invalid");
189 return;
190 }
191 StaticSubscriberExtension::OnReceiveEvent(data);
192 if (!jsObj_) {
193 EVENT_LOGE("Not found StaticSubscriberExtension.js");
194 return;
195 }
196
197 AbilityRuntime::HandleScope handleScope(jsRuntime_);
198 napi_env env = jsRuntime_.GetNapiEnv();
199 napi_value commonEventData = nullptr;
200 napi_create_object(env, &commonEventData);
201 Want want = data->GetWant();
202
203 napi_value wantAction = nullptr;
204 napi_create_string_utf8(env, want.GetAction().c_str(), want.GetAction().size(), &wantAction);
205 napi_set_named_property(env, commonEventData, "event", wantAction);
206 napi_value wantBundle = nullptr;
207 napi_create_string_utf8(env, want.GetBundle().c_str(), want.GetBundle().size(), &wantBundle);
208 napi_set_named_property(env, commonEventData, "bundleName", wantBundle);
209 napi_value dataCode = nullptr;
210 napi_create_int32(env, data->GetCode(), &dataCode);
211 napi_set_named_property(env, commonEventData, "code", dataCode);
212 napi_value dataNapi = nullptr;
213 napi_create_string_utf8(env, data->GetData().c_str(), data->GetData().size(), &dataNapi);
214 napi_set_named_property(env, commonEventData, "data", dataNapi);
215 napi_value napiParams = AppExecFwk::WrapWantParams(
216 env, want.GetParams());
217 napi_set_named_property(env, commonEventData, "parameters", napiParams);
218
219 napi_value argv[] = {commonEventData};
220 napi_value obj = jsObj_->GetNapiValue();
221 if (obj == nullptr) {
222 EVENT_LOGE("Failed to get StaticSubscriberExtension object");
223 return;
224 }
225
226 napi_value method = nullptr;
227 napi_get_named_property(env, obj, "onReceiveEvent", &method);
228 if (method == nullptr) {
229 EVENT_LOGE("Failed to get onReceiveEvent from StaticSubscriberExtension object");
230 return;
231 }
232 napi_call_function(env, obj, method, ARGC_ONE, argv, nullptr);
233 EVENT_LOGD("JsStaticSubscriberExtension js receive event called.");
234 };
235 handler_->PostTask(task, "CommonEvent" + data->GetWant().GetAction());
236 }
237 } // namespace EventFwk
238 } // namespace OHOS
239