• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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_service_extension.h"
17 
18 #include "ability_info.h"
19 #include "bytrace.h"
20 #include "hilog_wrapper.h"
21 #include "js_extension_context.h"
22 #include "js_runtime.h"
23 #include "js_runtime_utils.h"
24 #include "js_service_extension_context.h"
25 #include "napi/native_api.h"
26 #include "napi/native_node_api.h"
27 #include "napi_common_configuration.h"
28 #include "napi_common_want.h"
29 #include "napi_remote_object.h"
30 
31 namespace OHOS {
32 namespace AbilityRuntime {
33 namespace {
34 constexpr size_t ARGC_ONE = 1;
35 constexpr size_t ARGC_TWO = 2;
36 }
37 
38 using namespace OHOS::AppExecFwk;
Create(const std::unique_ptr<Runtime> & runtime)39 JsServiceExtension* JsServiceExtension::Create(const std::unique_ptr<Runtime>& runtime)
40 {
41     return new JsServiceExtension(static_cast<JsRuntime&>(*runtime));
42 }
43 
JsServiceExtension(JsRuntime & jsRuntime)44 JsServiceExtension::JsServiceExtension(JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
45 JsServiceExtension::~JsServiceExtension() = default;
46 
Init(const std::shared_ptr<AbilityLocalRecord> & record,const std::shared_ptr<OHOSApplication> & application,std::shared_ptr<AbilityHandler> & handler,const sptr<IRemoteObject> & token)47 void JsServiceExtension::Init(const std::shared_ptr<AbilityLocalRecord> &record,
48     const std::shared_ptr<OHOSApplication> &application, std::shared_ptr<AbilityHandler> &handler,
49     const sptr<IRemoteObject> &token)
50 {
51     ServiceExtension::Init(record, application, handler, token);
52     std::string srcPath = "";
53     GetSrcPath(srcPath);
54     if (srcPath.empty()) {
55         HILOG_ERROR("Failed to get srcPath");
56         return;
57     }
58 
59     std::string moduleName(Extension::abilityInfo_->moduleName);
60     moduleName.append("::").append(abilityInfo_->name);
61     HILOG_INFO("JsServiceExtension::Init module:%{public}s,srcPath:%{public}s.", moduleName.c_str(), srcPath.c_str());
62     HandleScope handleScope(jsRuntime_);
63     auto& engine = jsRuntime_.GetNativeEngine();
64 
65     jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath);
66     if (jsObj_ == nullptr) {
67         HILOG_ERROR("Failed to get jsObj_");
68         return;
69     }
70     HILOG_INFO("JsServiceExtension::Init ConvertNativeValueTo.");
71     NativeObject* obj = ConvertNativeValueTo<NativeObject>(jsObj_->Get());
72     if (obj == nullptr) {
73         HILOG_ERROR("Failed to get JsServiceExtension object");
74         return;
75     }
76 
77     auto context = GetContext();
78     if (context == nullptr) {
79         HILOG_ERROR("Failed to get context");
80         return;
81     }
82     HILOG_INFO("JsServiceExtension::Init CreateJsServiceExtensionContext.");
83     NativeValue* contextObj = CreateJsServiceExtensionContext(engine, context);
84     shellContextRef_ = jsRuntime_.LoadSystemModule("application.ServiceExtensionContext", &contextObj, ARGC_ONE);
85     contextObj = shellContextRef_->Get();
86     HILOG_INFO("JsServiceExtension::Init Bind.");
87     context->Bind(jsRuntime_, shellContextRef_.get());
88     HILOG_INFO("JsServiceExtension::SetProperty.");
89     obj->SetProperty("context", contextObj);
90 
91     auto nativeObj = ConvertNativeValueTo<NativeObject>(contextObj);
92     if (nativeObj == nullptr) {
93         HILOG_ERROR("Failed to get service extension native object");
94         return;
95     }
96 
97     HILOG_INFO("Set service extension context pointer: %{public}p", context.get());
98 
99     nativeObj->SetNativePointer(new std::weak_ptr<AbilityRuntime::Context>(context),
100         [](NativeEngine*, void* data, void*) {
101             HILOG_INFO("Finalizer for weak_ptr service extension context is called");
102             delete static_cast<std::weak_ptr<AbilityRuntime::Context>*>(data);
103         }, nullptr);
104 
105     HILOG_INFO("JsServiceExtension::Init end.");
106 }
107 
OnStart(const AAFwk::Want & want)108 void JsServiceExtension::OnStart(const AAFwk::Want &want)
109 {
110     Extension::OnStart(want);
111     HILOG_INFO("JsServiceExtension OnStart begin..");
112     HandleScope handleScope(jsRuntime_);
113     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
114     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
115     NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
116     NativeValue* argv[] = {nativeWant};
117     CallObjectMethod("onCreate", argv, ARGC_ONE);
118     HILOG_INFO("%{public}s end.", __func__);
119 }
120 
OnStop()121 void JsServiceExtension::OnStop()
122 {
123     ServiceExtension::OnStop();
124     HILOG_INFO("JsServiceExtension OnStop begin.");
125     CallObjectMethod("onDestroy");
126     bool ret = ConnectionManager::GetInstance().DisconnectCaller(GetContext()->GetToken());
127     if (ret) {
128         ConnectionManager::GetInstance().ReportConnectionLeakEvent(getpid(), gettid());
129         HILOG_INFO("The service extension connection is not disconnected.");
130     }
131     HILOG_INFO("%{public}s end.", __func__);
132 }
133 
OnConnect(const AAFwk::Want & want)134 sptr<IRemoteObject> JsServiceExtension::OnConnect(const AAFwk::Want &want)
135 {
136     BYTRACE_NAME(BYTRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
137     Extension::OnConnect(want);
138     HILOG_INFO("%{public}s begin.", __func__);
139     HandleScope handleScope(jsRuntime_);
140     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
141     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
142     NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
143     NativeValue* argv[] = {nativeWant};
144     if (!jsObj_) {
145         HILOG_WARN("Not found ServiceExtension.js");
146         return nullptr;
147     }
148 
149     NativeValue* value = jsObj_->Get();
150     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
151     if (obj == nullptr) {
152         HILOG_ERROR("Failed to get ServiceExtension object");
153         return nullptr;
154     }
155 
156     NativeValue* method = obj->GetProperty("onConnect");
157     if (method == nullptr) {
158         HILOG_ERROR("Failed to get onConnect from ServiceExtension object");
159         return nullptr;
160     }
161     HILOG_INFO("JsServiceExtension::CallFunction onConnect, success");
162     NativeValue* remoteNative = nativeEngine->CallFunction(value, method, argv, ARGC_ONE);
163     if (remoteNative == nullptr) {
164         HILOG_ERROR("remoteNative nullptr.");
165     }
166     auto remoteObj = NAPI_ohos_rpc_getNativeRemoteObject(
167         reinterpret_cast<napi_env>(nativeEngine), reinterpret_cast<napi_value>(remoteNative));
168     if (remoteObj == nullptr) {
169         HILOG_ERROR("remoteObj nullptr.");
170     }
171     return remoteObj;
172 }
173 
OnDisconnect(const AAFwk::Want & want)174 void JsServiceExtension::OnDisconnect(const AAFwk::Want &want)
175 {
176     BYTRACE_NAME(BYTRACE_TAG_ABILITY_MANAGER, __PRETTY_FUNCTION__);
177     Extension::OnDisconnect(want);
178     HILOG_INFO("%{public}s begin.", __func__);
179     HandleScope handleScope(jsRuntime_);
180     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
181     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
182     NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
183     NativeValue* argv[] = {nativeWant};
184     if (!jsObj_) {
185         HILOG_WARN("Not found ServiceExtension.js");
186         return;
187     }
188 
189     NativeValue* value = jsObj_->Get();
190     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
191     if (obj == nullptr) {
192         HILOG_ERROR("Failed to get ServiceExtension object");
193         return;
194     }
195 
196     NativeValue* method = obj->GetProperty("onDisconnect");
197     if (method == nullptr) {
198         HILOG_ERROR("Failed to get onDisconnect from ServiceExtension object");
199         return;
200     }
201     nativeEngine->CallFunction(value, method, argv, ARGC_ONE);
202     HILOG_INFO("%{public}s end.", __func__);
203 }
204 
OnCommand(const AAFwk::Want & want,bool restart,int startId)205 void JsServiceExtension::OnCommand(const AAFwk::Want &want, bool restart, int startId)
206 {
207     Extension::OnCommand(want, restart, startId);
208     HILOG_INFO("%{public}s begin restart=%{public}s,startId=%{public}d.",
209         __func__,
210         restart ? "true" : "false",
211         startId);
212     // wrap want
213     HandleScope handleScope(jsRuntime_);
214     NativeEngine* nativeEngine = &jsRuntime_.GetNativeEngine();
215     napi_value napiWant = OHOS::AppExecFwk::WrapWant(reinterpret_cast<napi_env>(nativeEngine), want);
216     NativeValue* nativeWant = reinterpret_cast<NativeValue*>(napiWant);
217     // wrap startId
218     napi_value napiStartId = nullptr;
219     napi_create_int32(reinterpret_cast<napi_env>(nativeEngine), startId, &napiStartId);
220     NativeValue* nativeStartId = reinterpret_cast<NativeValue*>(napiStartId);
221     NativeValue* argv[] = {nativeWant, nativeStartId};
222     CallObjectMethod("onRequest", argv, ARGC_TWO);
223     HILOG_INFO("%{public}s end.", __func__);
224 }
225 
CallObjectMethod(const char * name,NativeValue * const * argv,size_t argc)226 NativeValue* JsServiceExtension::CallObjectMethod(const char* name, NativeValue* const* argv, size_t argc)
227 {
228     HILOG_INFO("JsServiceExtension::CallObjectMethod(%{public}s), begin", name);
229 
230     if (!jsObj_) {
231         HILOG_WARN("Not found ServiceExtension.js");
232         return nullptr;
233     }
234 
235     HandleScope handleScope(jsRuntime_);
236     auto& nativeEngine = jsRuntime_.GetNativeEngine();
237 
238     NativeValue* value = jsObj_->Get();
239     NativeObject* obj = ConvertNativeValueTo<NativeObject>(value);
240     if (obj == nullptr) {
241         HILOG_ERROR("Failed to get ServiceExtension object");
242         return nullptr;
243     }
244 
245     NativeValue* method = obj->GetProperty(name);
246     if (method == nullptr || method->TypeOf() != NATIVE_FUNCTION) {
247         HILOG_ERROR("Failed to get '%{public}s' from ServiceExtension object", name);
248         return nullptr;
249     }
250     HILOG_INFO("JsServiceExtension::CallFunction(%{public}s), success", name);
251     return nativeEngine.CallFunction(value, method, argv, argc);
252 }
253 
GetSrcPath(std::string & srcPath)254 void JsServiceExtension::GetSrcPath(std::string &srcPath)
255 {
256     if (!Extension::abilityInfo_->isModuleJson) {
257         /* temporary compatibility api8 + config.json */
258         srcPath.append(Extension::abilityInfo_->package);
259         srcPath.append("/assets/js/");
260         if (!Extension::abilityInfo_->srcPath.empty()) {
261             srcPath.append(Extension::abilityInfo_->srcPath);
262         }
263         srcPath.append("/").append(Extension::abilityInfo_->name).append(".abc");
264         return;
265     }
266 
267     if (!Extension::abilityInfo_->srcEntrance.empty()) {
268         srcPath.append(Extension::abilityInfo_->moduleName + "/");
269         srcPath.append(Extension::abilityInfo_->srcEntrance);
270         srcPath.erase(srcPath.rfind('.'));
271         srcPath.append(".abc");
272     }
273 }
274 
OnConfigurationUpdated(const AppExecFwk::Configuration & configuration)275 void JsServiceExtension::OnConfigurationUpdated(const AppExecFwk::Configuration& configuration)
276 {
277     Extension::OnConfigurationUpdated(configuration);
278     HILOG_INFO("%{public}s called.", __func__);
279 
280     HandleScope handleScope(jsRuntime_);
281     auto& nativeEngine = jsRuntime_.GetNativeEngine();
282 
283     // Notify extension context
284     auto fullConfig = GetContext()->GetConfiguration();
285     if (!fullConfig) {
286         HILOG_ERROR("configuration is nullptr.");
287         return;
288     }
289     JsExtensionContext::ConfigurationUpdated(&nativeEngine, shellContextRef_, fullConfig);
290 
291     napi_value napiConfiguration = OHOS::AppExecFwk::WrapConfiguration(
292         reinterpret_cast<napi_env>(&nativeEngine), *fullConfig);
293     NativeValue* jsConfiguration = reinterpret_cast<NativeValue*>(napiConfiguration);
294     CallObjectMethod("onConfigurationUpdated", &jsConfiguration, 1);
295 }
296 }
297 }
298