1 /*
2  * Copyright (c) 2022-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_enterprise_admin_extension.h"
17 
18 #include <string>
19 
20 #include "ability_handler.h"
21 #include "edm_log.h"
22 #include "enterprise_admin_extension.h"
23 #include "enterprise_admin_stub_impl.h"
24 #include "js_enterprise_admin_extension_context.h"
25 #include "js_runtime.h"
26 #include "js_runtime_utils.h"
27 #include "runtime.h"
28 
29 namespace OHOS {
30 namespace EDM {
31 constexpr size_t JS_NAPI_ARGC_ZERO = 0;
32 constexpr size_t JS_NAPI_ARGC_ONE = 1;
33 constexpr size_t JS_NAPI_ARGC_TWO = 2;
34 
Create(const std::unique_ptr<AbilityRuntime::Runtime> & runtime)35 JsEnterpriseAdminExtension* JsEnterpriseAdminExtension::Create(const std::unique_ptr<AbilityRuntime::Runtime>& runtime)
36 {
37     return new JsEnterpriseAdminExtension(static_cast<AbilityRuntime::JsRuntime&>(*runtime));
38 }
39 
JsEnterpriseAdminExtension(AbilityRuntime::JsRuntime & jsRuntime)40 JsEnterpriseAdminExtension::JsEnterpriseAdminExtension(AbilityRuntime::JsRuntime& jsRuntime) : jsRuntime_(jsRuntime) {}
~JsEnterpriseAdminExtension()41 JsEnterpriseAdminExtension::~JsEnterpriseAdminExtension()
42 {
43     EDMLOGD("Js enterprise admin extension destructor.");
44     jsRuntime_.FreeNativeReference(std::move(jsObj_));
45 }
46 
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)47 void JsEnterpriseAdminExtension::Init(const std::shared_ptr<AppExecFwk::AbilityLocalRecord>& record,
48     const std::shared_ptr<AppExecFwk::OHOSApplication>& application,
49     std::shared_ptr<AppExecFwk::AbilityHandler>& handler,
50     const sptr<IRemoteObject>& token)
51 {
52     EnterpriseAdminExtension::Init(record, application, handler, token);
53     std::string srcPath;
54     GetSrcPath(srcPath);
55     if (srcPath.empty()) {
56         EDMLOGI("JsEnterpriseAdminExtension Failed to get srcPath");
57         return;
58     }
59 
60     std::string moduleName(Extension::abilityInfo_->moduleName);
61     moduleName.append("::").append(abilityInfo_->name);
62     EDMLOGI("JsEnterpriseAdminExtension::Init moduleName:%{public}s,srcPath:%{public}s.",
63         moduleName.c_str(), srcPath.c_str());
64     AbilityRuntime::HandleScope handleScope(jsRuntime_);
65 
66     jsObj_ = jsRuntime_.LoadModule(moduleName, srcPath, abilityInfo_->hapPath,
67         Extension::abilityInfo_->compileMode == AbilityRuntime::CompileMode::ES_MODULE);
68     if (jsObj_ == nullptr) {
69         EDMLOGI("JsEnterpriseAdminExtension Failed to get jsObj_");
70         return;
71     }
72     EDMLOGI("JsEnterpriseAdminExtension::Init ConvertNativeValueTo.");
73     JsEnterpriseAdminExtensionContextInit();
74 }
75 
JsEnterpriseAdminExtensionContextInit()76 void JsEnterpriseAdminExtension::JsEnterpriseAdminExtensionContextInit()
77 {
78     napi_value obj = jsObj_->GetNapiValue();
79 
80     auto env = jsRuntime_.GetNapiEnv();
81     auto context = GetContext();
82     if (context == nullptr) {
83         EDMLOGI("JsEnterpriseAdminExtension Failed to get context");
84         return;
85     }
86     EDMLOGI("JsEnterpriseAdminExtension::Init CreateJsEnterpriseAdminExtensionContext.");
87     napi_value contextObj = CreateJsEnterpriseAdminExtensionContext(env, context);
88     auto shellContextRef = jsRuntime_.LoadSystemModule("enterprise.EnterpriseAdminExtensionContext",
89         &contextObj, JS_NAPI_ARGC_ONE);
90     contextObj = shellContextRef->GetNapiValue();
91     EDMLOGI("JsEnterpriseAdminExtension::Init Bind.");
92     context->Bind(jsRuntime_, shellContextRef.release());
93     EDMLOGI("JsEnterpriseAdminExtension::SetProperty.");
94     napi_set_named_property(env, obj, "context", contextObj);
95 
96     EDMLOGI("Set enterprise admin extension context");
97 
98     napi_wrap(env, contextObj, new std::weak_ptr<AbilityRuntime::Context>(context),
99         [](napi_env env, void* data, void*) {
100             EDMLOGI("Finalizer for weak_ptr service extension context is called");
101             delete static_cast<std::weak_ptr<AbilityRuntime::Context>*>(data);
102         }, nullptr, nullptr);
103 
104     EDMLOGI("JsEnterpriseAdminExtension::Init end.");
105 }
106 
OnStart(const AAFwk::Want & want)107 void JsEnterpriseAdminExtension::OnStart(const AAFwk::Want& want)
108 {
109     EDMLOGI("JsEnterpriseAdminExtension OnStart begin");
110     AbilityRuntime::Extension::OnStart(want);
111     auto task = [this]() {
112         CallObjectMethod("onStart", nullptr, JS_NAPI_ARGC_ZERO);
113     };
114     handler_->PostTask(task);
115 }
116 
OnStop()117 void JsEnterpriseAdminExtension::OnStop()
118 {
119     AbilityRuntime::Extension::OnStop();
120     EDMLOGI("JsEnterpriseAdminExtension %{public}s end.", __func__);
121 }
122 
OnConnect(const AAFwk::Want & want)123 sptr<IRemoteObject> JsEnterpriseAdminExtension::OnConnect(const AAFwk::Want& want)
124 {
125     AbilityRuntime::Extension::OnConnect(want);
126     EDMLOGI("EnterpriseAdminExtension %{public}s begin.", __func__);
127     sptr<EnterpriseAdminStubImpl> remoteObject = new (std::nothrow) EnterpriseAdminStubImpl(
128         std::static_pointer_cast<JsEnterpriseAdminExtension>(shared_from_this()));
129 
130     if (remoteObject == nullptr) {
131         EDMLOGI("OnConnect get null");
132         return remoteObject;
133     }
134     EDMLOGI("JsEnterpriseAdminExtension %{public}s end. ", __func__);
135     return remoteObject->AsObject();
136 }
137 
OnDisconnect(const AAFwk::Want & want)138 void JsEnterpriseAdminExtension::OnDisconnect(const AAFwk::Want& want)
139 {
140     EDMLOGI("JsEnterpriseAdminExtension %{public}s begin.", __func__);
141     AbilityRuntime::Extension::OnDisconnect(want);
142 }
143 
OnAdminEnabled()144 void JsEnterpriseAdminExtension::OnAdminEnabled()
145 {
146     EDMLOGI("JsEnterpriseAdminExtension::OnAdminEnabled");
147     auto task = [this]() {
148         CallObjectMethod("onAdminEnabled", nullptr, JS_NAPI_ARGC_ZERO);
149     };
150     handler_->PostTask(task);
151 }
152 
OnAdminDisabled()153 void JsEnterpriseAdminExtension::OnAdminDisabled()
154 {
155     EDMLOGI("JsEnterpriseAdminExtension::OnAdminDisabled");
156     auto task = [this]() {
157         CallObjectMethod("onAdminDisabled", nullptr, JS_NAPI_ARGC_ZERO);
158     };
159     handler_->PostTask(task);
160 }
161 
OnBundleAdded(const std::string & bundleName,int32_t accountId)162 void JsEnterpriseAdminExtension::OnBundleAdded(const std::string &bundleName, int32_t accountId)
163 {
164     EDMLOGI("JsEnterpriseAdminExtension::OnBundleAdded");
165     auto task = [bundleName, accountId, this]() {
166         auto env = jsRuntime_.GetNapiEnv();
167         napi_value argv[] = { AbilityRuntime::CreateJsValue(env, bundleName),
168             AbilityRuntime::CreateJsValue(env, accountId) };
169         CallObjectMethod("onBundleAdded", argv, JS_NAPI_ARGC_TWO);
170     };
171     handler_->PostTask(task);
172 }
173 
OnBundleRemoved(const std::string & bundleName,int32_t accountId)174 void JsEnterpriseAdminExtension::OnBundleRemoved(const std::string &bundleName, int32_t accountId)
175 {
176     EDMLOGI("JsEnterpriseAdminExtension::OnBundleRemoved");
177     auto task = [bundleName, accountId, this]() {
178         auto env = jsRuntime_.GetNapiEnv();
179         napi_value argv[] = { AbilityRuntime::CreateJsValue(env, bundleName),
180             AbilityRuntime::CreateJsValue(env, accountId) };
181         CallObjectMethod("onBundleRemoved", argv, JS_NAPI_ARGC_TWO);
182     };
183     handler_->PostTask(task);
184 }
185 
OnAppStart(const std::string & bundleName)186 void JsEnterpriseAdminExtension::OnAppStart(const std::string &bundleName)
187 {
188     EDMLOGI("JsEnterpriseAdminExtension::OnAppStart");
189     auto task = [bundleName, this]() {
190         auto env = jsRuntime_.GetNapiEnv();
191         napi_value argv[] = { AbilityRuntime::CreateJsValue(env, bundleName) };
192         CallObjectMethod("onAppStart", argv, JS_NAPI_ARGC_ONE);
193     };
194     handler_->PostTask(task);
195 }
196 
OnAppStop(const std::string & bundleName)197 void JsEnterpriseAdminExtension::OnAppStop(const std::string &bundleName)
198 {
199     EDMLOGI("JsEnterpriseAdminExtension::OnAppStop");
200     auto task = [bundleName, this]() {
201         auto env = jsRuntime_.GetNapiEnv();
202         napi_value argv[] = { AbilityRuntime::CreateJsValue(env, bundleName) };
203         CallObjectMethod("onAppStop", argv, JS_NAPI_ARGC_ONE);
204     };
205     handler_->PostTask(task);
206 }
207 
OnSystemUpdate(const UpdateInfo & updateInfo)208 void JsEnterpriseAdminExtension::OnSystemUpdate(const UpdateInfo &updateInfo)
209 {
210     EDMLOGI("JsEnterpriseAdminExtension::OnSystemUpdate");
211     auto task = [updateInfo, this]() {
212         auto env = jsRuntime_.GetNapiEnv();
213         napi_value argv[] = { CreateUpdateInfoObject(env, updateInfo) };
214         CallObjectMethod("onSystemUpdate", argv, JS_NAPI_ARGC_ONE);
215     };
216     handler_->PostTask(task);
217 }
218 
CreateUpdateInfoObject(napi_env env,const UpdateInfo & updateInfo)219 napi_value JsEnterpriseAdminExtension::CreateUpdateInfoObject(napi_env env, const UpdateInfo &updateInfo)
220 {
221     napi_value nSystemUpdateInfo = nullptr;
222     NAPI_CALL(env, napi_create_object(env, &nSystemUpdateInfo));
223 
224     napi_value nVersionName = nullptr;
225     NAPI_CALL(env, napi_create_string_utf8(env, updateInfo.version.c_str(), NAPI_AUTO_LENGTH, &nVersionName));
226     NAPI_CALL(env, napi_set_named_property(env, nSystemUpdateInfo, "versionName", nVersionName));
227 
228     napi_value nFirstReceivedTime = nullptr;
229     NAPI_CALL(env, napi_create_int64(env, updateInfo.firstReceivedTime, &nFirstReceivedTime));
230     NAPI_CALL(env, napi_set_named_property(env, nSystemUpdateInfo, "firstReceivedTime", nFirstReceivedTime));
231 
232     napi_value nPackageType = nullptr;
233     NAPI_CALL(env, napi_create_string_utf8(env, updateInfo.packageType.c_str(), NAPI_AUTO_LENGTH, &nPackageType));
234     NAPI_CALL(env, napi_set_named_property(env, nSystemUpdateInfo, "packageType", nPackageType));
235 
236     return nSystemUpdateInfo;
237 }
238 
CallObjectMethod(const char * name,napi_value * argv,size_t argc)239 napi_value JsEnterpriseAdminExtension::CallObjectMethod(const char* name, napi_value* argv, size_t argc)
240 {
241     EDMLOGI("JsEnterpriseAdminExtension::CallObjectMethod(%{public}s), begin", name);
242 
243     if (!jsObj_) {
244         EDMLOGW("Not found EnterpriseAdminExtension.js");
245         return nullptr;
246     }
247 
248     AbilityRuntime::HandleScope handleScope(jsRuntime_);
249     auto env = jsRuntime_.GetNapiEnv();
250 
251     napi_value value = jsObj_->GetNapiValue();
252     if (value == nullptr) {
253         EDMLOGE("Failed to get EnterpriseAdminExtension object");
254         return nullptr;
255     }
256     napi_value method = nullptr;
257     napi_get_named_property(env, value, name, &method);
258 
259     if (method == nullptr) {
260         EDMLOGE("Failed to get '%{public}s' from EnterpriseAdminExtension object", name);
261         return nullptr;
262     }
263     napi_valuetype valueType = napi_undefined;
264     napi_typeof(env, method, &valueType);
265     if (valueType != napi_function) {
266         EDMLOGE("'%{public}s' is not function", name);
267         return nullptr;
268     }
269 
270     EDMLOGI("JsEnterpriseAdminExtension::CallFunction(%{public}s), success", name);
271     napi_value result = nullptr;
272     napi_status status = napi_call_function(env, value, method, argc, argv, &result);
273     if (status != napi_ok) {
274         EDMLOGE("Failed to call function");
275     }
276     return result;
277 }
278 
GetSrcPath(std::string & srcPath)279 void JsEnterpriseAdminExtension::GetSrcPath(std::string& srcPath)
280 {
281     if (!Extension::abilityInfo_->srcEntrance.empty()) {
282         srcPath.append(Extension::abilityInfo_->moduleName + "/");
283         srcPath.append(Extension::abilityInfo_->srcEntrance);
284         srcPath.erase(srcPath.rfind('.'));
285         srcPath.append(".abc");
286     }
287 }
288 } // namespace EDM
289 } // namespace OHOS