• 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 
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