1 /*
2 * Copyright (c) 2020-2021 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_ability_impl.h"
17 #include "ace_event_error_code.h"
18 #include "ace_log.h"
19 #include "component.h"
20 #include "component_utils.h"
21 #include "fatal_handler.h"
22 #include "js_app_context.h"
23 #include "js_app_environment.h"
24 #include "js_profiler.h"
25 #include "module_manager.h"
26 #include "presets/localization_module.h"
27 #include "presets/timer_module.h"
28 #include "securec.h"
29
30 namespace OHOS {
31 namespace ACELite {
InitEnvironment(const char * const abilityPath,const char * const bundleName,uint16_t token)32 void JSAbilityImpl::InitEnvironment(const char * const abilityPath, const char * const bundleName, uint16_t token)
33 {
34 if ((abilityPath == nullptr) || strlen(abilityPath) == 0 || (bundleName == nullptr) || strlen(bundleName) == 0) {
35 HILOG_ERROR(HILOG_MODULE_ACE, "invalid input parameters");
36 return;
37 }
38
39 if (isEnvInit_) {
40 HILOG_ERROR(HILOG_MODULE_ACE, "already initialized, return");
41 return;
42 }
43 // init engine && js fwk
44 JsAppEnvironment *appJsEnv = JsAppEnvironment::GetInstance();
45 appContext_ = JsAppContext::GetInstance();
46 // check if we should use snapshot mode, do this before everything,
47 // but after debugger config is set
48 appJsEnv->InitRuntimeMode();
49 appContext_->SetCurrentAbilityInfo(abilityPath, bundleName, token);
50 appContext_->SetTopJSAbilityImpl(this);
51 appJsEnv->InitJsFramework();
52 appContext_->LoadApiVersion();
53
54 // initialize js object after engine started up
55 abilityModel_ = UNDEFINED;
56 nativeElement_ = UNDEFINED;
57 isEnvInit_ = true;
58
59 // relocate app.js fullpath
60 const char * const appJSFileName = (appJsEnv->IsSnapshotMode()) ? "app.bc" : "app.js";
61 char *fileFullPath = RelocateJSSourceFilePath(abilityPath, appJSFileName);
62 if (fileFullPath == nullptr) {
63 HILOG_ERROR(HILOG_MODULE_ACE, "relocate js file failed");
64 ACE_ERROR_CODE_PRINT(EXCE_ACE_FWK_LAUNCH_FAILED, EXCE_ACE_APP_ENTRY_MISSING);
65 return;
66 }
67
68 appContext_->SetAbilityState(TopAbilityState::ABILITY_INITIALIZED);
69 START_TRACING(APP_CODE_EVAL);
70 abilityModel_ = appContext_->Eval(fileFullPath, strlen(fileFullPath), true); // generate global.$app js object
71 STOP_TRACING();
72
73 ace_free(fileFullPath);
74 fileFullPath = nullptr;
75 router_ = new Router();
76 if (router_ == nullptr) {
77 HILOG_ERROR(HILOG_MODULE_ACE, "malloc router heap memory failed.");
78 return;
79 }
80 }
81
CleanUp()82 void JSAbilityImpl::CleanUp()
83 {
84 if (appContext_ == nullptr) {
85 return;
86 }
87 appContext_->SetAbilityState(TopAbilityState::ABILITY_DESTROYING);
88 if (!isEnvInit_) {
89 return;
90 }
91 START_TRACING(APP_ON_DESTROY);
92 // clean up user's js
93 InvokeOnDestroy();
94 STOP_TRACING();
95
96 // delete router's resources about page
97 if (router_ != nullptr) {
98 delete router_;
99 router_ = nullptr;
100 }
101 TimersModule::Clear();
102 LocalModule::Clear();
103
104 appContext_->ClearContext();
105
106 ModuleManager::GetInstance()->OnTerminate();
107 JsAppEnvironment::GetInstance()->Cleanup();
108 isEnvInit_ = false;
109 appContext_->SetAbilityState(TopAbilityState::ABILITY_DESTROYED);
110 OUTPUT_TRACE();
111 }
112
DeliverCreate(const char * param)113 void JSAbilityImpl::DeliverCreate(const char *param)
114 {
115 if (appContext_ == nullptr) {
116 return;
117 }
118 appContext_->SetAbilityState(TopAbilityState::ABILITY_LAUNCHING);
119 START_TRACING(APP_ON_CREATE);
120 // call InvokeOnCreate
121 InvokeOnCreate();
122 STOP_TRACING();
123 // if we have done the render or not initialized yet, don't call render
124 if (rendered_) {
125 ACE_ERROR_CODE_PRINT(EXCE_ACE_FWK_LAUNCH_FAILED, EXCE_ACE_APP_RENDER_FAILED);
126 return;
127 }
128 // call render to setup user interface
129 jerry_value_t object = UNDEFINED;
130 if (param == nullptr) {
131 object = jerry_create_object();
132 JerrySetStringProperty(object, ROUTER_PAGE_URI, PATH_DEFAULT);
133 } else {
134 object = jerry_json_parse(reinterpret_cast<const jerry_char_t *>(param), strlen(param));
135 }
136 if (router_) {
137 jerry_release_value(router_->Replace(object, false));
138 rendered_ = true;
139 }
140 jerry_release_value(object);
141 appContext_->SetAbilityState(TopAbilityState::ABILITY_LAUNCHDONE);
142 }
143
Show() const144 void JSAbilityImpl::Show() const
145 {
146 if (appContext_ == nullptr) {
147 return;
148 }
149 if (router_ == nullptr) {
150 HILOG_ERROR(HILOG_MODULE_ACE, "no router instance to perform the show request");
151 return;
152 }
153 appContext_->SetAbilityState(TopAbilityState::ABILITY_SHOWING);
154 router_->Show();
155 FatalHandler::GetInstance().NotifyVisibleStatusChange(true);
156 appContext_->SetAbilityState(TopAbilityState::ABILITY_SHOWN);
157 }
158
Hide() const159 void JSAbilityImpl::Hide() const
160 {
161 if (appContext_ == nullptr) {
162 return;
163 }
164 if (router_ == nullptr) {
165 HILOG_ERROR(HILOG_MODULE_ACE, "no router instance to perform the hide request");
166 return;
167 }
168 appContext_->SetAbilityState(TopAbilityState::ABILITY_HIDING);
169 router_->Hide();
170 FatalHandler::GetInstance().NotifyVisibleStatusChange(false);
171 appContext_->SetAbilityState(TopAbilityState::ABILITY_HIDDEN);
172 }
173
NotifyBackPressed() const174 void JSAbilityImpl::NotifyBackPressed() const
175 {
176 if (appContext_ == nullptr) {
177 return;
178 }
179
180 InvokeOnBackPressed();
181
182 appContext_->TerminateAbility();
183 }
184
InvokeOnCreate() const185 void JSAbilityImpl::InvokeOnCreate() const
186 {
187 if (IS_UNDEFINED(abilityModel_)) {
188 HILOG_ERROR(HILOG_MODULE_ACE, "view model is undefined when call user's init");
189 return;
190 }
191 jerry_value_t onCreateFunction = jerryx_get_property_str(abilityModel_, ABILITY_LIFECYCLE_CALLBACK_ON_CREATE);
192 if (IS_UNDEFINED(onCreateFunction)) {
193 // user does not set onInit method
194 return;
195 }
196 CallJSFunctionAutoRelease(onCreateFunction, abilityModel_, nullptr, 0);
197 jerry_release_value(onCreateFunction);
198 }
199
InvokeOnDestroy() const200 void JSAbilityImpl::InvokeOnDestroy() const
201 {
202 InvokeMethodWithoutParameter(ABILITY_LIFECYCLE_CALLBACK_ON_DESTROY);
203 // release FeatureAbility object
204 jerry_release_value(abilityModel_);
205 }
206
InvokeOnBackPressed() const207 void JSAbilityImpl::InvokeOnBackPressed() const
208 {
209 InvokeMethodWithoutParameter(BACK_PRESSED_NAME);
210 }
211
InvokeMethodWithoutParameter(const char * const name) const212 void JSAbilityImpl::InvokeMethodWithoutParameter(const char * const name) const
213 {
214 if (FatalHandler::GetInstance().IsJSRuntimeFatal()) {
215 // can not continue to involve any JS object creating on engine in case runtime fatal
216 return;
217 }
218 if ((name == nullptr) || strlen(name) == 0) {
219 return;
220 }
221
222 jerry_value_t function = jerryx_get_property_str(abilityModel_, name);
223 if (IS_UNDEFINED(function)) {
224 // user does not set onBackpress method
225 return;
226 }
227 CallJSFunctionAutoRelease(function, abilityModel_, nullptr, 0);
228 jerry_release_value(function);
229 }
230 } // namespace ACELite
231 } // namespace OHOS
232