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