1 /*
2  * Copyright (c) 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 "adapter/ohos/entrance/pa_engine/pa_backend.h"
17 
18 #include "napi_remote_object.h"
19 
20 #include "ability.h"
21 #include "adapter/ohos/entrance/pa_engine/engine/common/js_backend_engine_loader.h"
22 #include "base/log/dump_log.h"
23 #include "base/log/event_report.h"
24 #include "base/utils/utils.h"
25 #include "frameworks/bridge/common/utils/utils.h"
26 
27 namespace OHOS::Ace {
28 namespace {
29 const char PA_MANIFEST_JSON[] = "manifest.json";
30 } // namespace
31 
Create()32 RefPtr<Backend> Backend::Create()
33 {
34     return AceType::MakeRefPtr<PaBackend>();
35 }
36 
~PaBackend()37 PaBackend::~PaBackend() noexcept
38 {
39     LOGI("PaBackend destructor.");
40 }
41 
Initialize(BackendType type,SrcLanguage language)42 bool PaBackend::Initialize(BackendType type, SrcLanguage language)
43 {
44     LOGI("PaBackend initialize begin.");
45     type_ = type;
46     language_ = language;
47 
48     CHECK_NULL_RETURN(jsBackendEngine_, false);
49     jsBackendEngine_->Initialize(type, language);
50     return true;
51 }
52 
LoadEngine(const char * libName,int32_t instanceId)53 void PaBackend::LoadEngine(const char* libName, int32_t instanceId)
54 {
55     auto& loader = JsBackendEngineLoader::Get(libName);
56     SetJsEngine(loader.CreateJsBackendEngine(instanceId));
57 }
58 
UpdateState(Backend::State state)59 void PaBackend::UpdateState(Backend::State state)
60 {
61     LOGI("UpdateState");
62     switch (state) {
63         case Backend::State::ON_CREATE:
64             break;
65         case Backend::State::ON_DESTROY:
66             if (jsBackendEngine_) {
67                 jsBackendEngine_->PostSyncTask(
68                     [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_)] {
69                         auto jsBackendEngine = weakEngine.Upgrade();
70                         CHECK_NULL_VOID(jsBackendEngine);
71                         jsBackendEngine->DestroyApplication("pa");
72                     }, "ArkUIPaBackendDestroyApplication");
73             }
74             break;
75         default:
76             LOGE("error State: %d", state);
77     }
78 }
79 
OnCommand(const OHOS::AAFwk::Want & want,int startId)80 void PaBackend::OnCommand(const OHOS::AAFwk::Want& want, int startId)
81 {
82     CHECK_NULL_VOID(jsBackendEngine_);
83     jsBackendEngine_->PostTask(
84         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), want, startId] {
85             auto jsBackendEngine = weakEngine.Upgrade();
86             CHECK_NULL_VOID(jsBackendEngine);
87             jsBackendEngine->OnCommand(want, startId);
88         }, "ArkUIPaBackendOnCommand");
89 }
90 
SetAssetManager(const RefPtr<AssetManager> & assetManager)91 void PaBackend::SetAssetManager(const RefPtr<AssetManager>& assetManager)
92 {
93     assetManager_ = assetManager;
94     CHECK_NULL_VOID(jsBackendEngine_);
95     jsBackendEngine_->SetAssetManager(assetManager);
96 }
97 
Insert(const Uri & uri,const OHOS::NativeRdb::ValuesBucket & value)98 int32_t PaBackend::Insert(const Uri& uri, const OHOS::NativeRdb::ValuesBucket& value)
99 {
100     int32_t ret = 0;
101     CallingInfo callingInfo;
102     NAPI_RemoteObject_getCallingInfo(callingInfo);
103     CHECK_NULL_RETURN(jsBackendEngine_, ret);
104     jsBackendEngine_->PostSyncTask(
105         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, value, callingInfo] {
106             auto jsBackendEngine = weakEngine.Upgrade();
107             if (jsBackendEngine != nullptr) {
108                 ret = jsBackendEngine->Insert(uri, value, callingInfo);
109             }
110         }, "ArkUIPaBackendInsert");
111     return ret;
112 }
113 
Call(const Uri & uri,const std::string & method,const std::string & arg,const AppExecFwk::PacMap & pacMap)114 std::shared_ptr<AppExecFwk::PacMap> PaBackend::Call(
115     const Uri& uri, const std::string& method, const std::string& arg, const AppExecFwk::PacMap& pacMap)
116 {
117     std::shared_ptr<AppExecFwk::PacMap> ret = nullptr;
118     CallingInfo callingInfo;
119     NAPI_RemoteObject_getCallingInfo(callingInfo);
120     CHECK_NULL_RETURN(jsBackendEngine_, ret);
121     jsBackendEngine_->PostSyncTask(
122         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, method, arg, pacMap, callingInfo] {
123             auto jsBackendEngine = weakEngine.Upgrade();
124             if (jsBackendEngine != nullptr) {
125                 ret = jsBackendEngine->Call(method, arg, pacMap, callingInfo);
126             }
127         }, "ArkUIPaBackendCall");
128     return ret;
129 }
130 
Query(const Uri & uri,const std::vector<std::string> & columns,const OHOS::NativeRdb::DataAbilityPredicates & predicates)131 std::shared_ptr<OHOS::NativeRdb::AbsSharedResultSet> PaBackend::Query(
132     const Uri& uri, const std::vector<std::string>& columns, const OHOS::NativeRdb::DataAbilityPredicates& predicates)
133 {
134     std::shared_ptr<OHOS::NativeRdb::AbsSharedResultSet> ret = nullptr;
135     CallingInfo callingInfo;
136     NAPI_RemoteObject_getCallingInfo(callingInfo);
137     CHECK_NULL_RETURN(jsBackendEngine_, ret);
138     jsBackendEngine_->PostSyncTask(
139         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, columns, predicates, callingInfo] {
140             auto jsBackendEngine = weakEngine.Upgrade();
141             if (jsBackendEngine != nullptr) {
142                 ret = jsBackendEngine->Query(uri, columns, predicates, callingInfo);
143             }
144         }, "ArkUIPaBackendQuery");
145     return ret;
146 }
147 
Update(const Uri & uri,const OHOS::NativeRdb::ValuesBucket & value,const OHOS::NativeRdb::DataAbilityPredicates & predicates)148 int32_t PaBackend::Update(const Uri& uri, const OHOS::NativeRdb::ValuesBucket& value,
149     const OHOS::NativeRdb::DataAbilityPredicates& predicates)
150 {
151     int32_t ret = 0;
152     CallingInfo callingInfo;
153     NAPI_RemoteObject_getCallingInfo(callingInfo);
154     CHECK_NULL_RETURN(jsBackendEngine_, ret);
155     jsBackendEngine_->PostSyncTask(
156         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, value, predicates, callingInfo] {
157             auto jsBackendEngine = weakEngine.Upgrade();
158             if (jsBackendEngine != nullptr) {
159                 ret = jsBackendEngine->Update(uri, value, predicates, callingInfo);
160             }
161         }, "ArkUIPaBackendUpdate");
162     return ret;
163 }
164 
Delete(const Uri & uri,const OHOS::NativeRdb::DataAbilityPredicates & predicates)165 int32_t PaBackend::Delete(const Uri& uri, const OHOS::NativeRdb::DataAbilityPredicates& predicates)
166 {
167     int32_t ret = 0;
168     CallingInfo callingInfo;
169     NAPI_RemoteObject_getCallingInfo(callingInfo);
170     CHECK_NULL_RETURN(jsBackendEngine_, ret);
171     jsBackendEngine_->PostSyncTask(
172         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, predicates, callingInfo] {
173             auto jsBackendEngine = weakEngine.Upgrade();
174             if (jsBackendEngine != nullptr) {
175                 ret = jsBackendEngine->Delete(uri, predicates, callingInfo);
176             }
177         }, "ArkUIPaBackendDelete");
178     return ret;
179 }
180 
BatchInsert(const Uri & uri,const std::vector<OHOS::NativeRdb::ValuesBucket> & values)181 int32_t PaBackend::BatchInsert(const Uri& uri, const std::vector<OHOS::NativeRdb::ValuesBucket>& values)
182 {
183     int32_t ret = 0;
184     CallingInfo callingInfo;
185     NAPI_RemoteObject_getCallingInfo(callingInfo);
186     CHECK_NULL_RETURN(jsBackendEngine_, ret);
187     jsBackendEngine_->PostSyncTask(
188         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, values, callingInfo] {
189             auto jsBackendEngine = weakEngine.Upgrade();
190             if (jsBackendEngine != nullptr) {
191                 ret = jsBackendEngine->BatchInsert(uri, values, callingInfo);
192             }
193         }, "ArkUIPaBackendBatchInsert");
194     return ret;
195 }
196 
GetType(const Uri & uri)197 std::string PaBackend::GetType(const Uri& uri)
198 {
199     std::string ret;
200     CallingInfo callingInfo;
201     NAPI_RemoteObject_getCallingInfo(callingInfo);
202     CHECK_NULL_RETURN(jsBackendEngine_, ret);
203     jsBackendEngine_->PostSyncTask(
204         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, callingInfo] {
205             auto jsBackendEngine = weakEngine.Upgrade();
206             if (jsBackendEngine != nullptr) {
207                 ret = jsBackendEngine->GetType(uri, callingInfo);
208             }
209         }, "ArkUIPaBackendGetType");
210     return ret;
211 }
212 
GetFileTypes(const Uri & uri,const std::string & mimeTypeFilter)213 std::vector<std::string> PaBackend::GetFileTypes(const Uri& uri, const std::string& mimeTypeFilter)
214 {
215     std::vector<std::string> ret;
216     CallingInfo callingInfo;
217     NAPI_RemoteObject_getCallingInfo(callingInfo);
218     CHECK_NULL_RETURN(jsBackendEngine_, ret);
219     jsBackendEngine_->PostSyncTask(
220         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, mimeTypeFilter, callingInfo] {
221             auto jsBackendEngine = weakEngine.Upgrade();
222             if (jsBackendEngine != nullptr) {
223                 ret = jsBackendEngine->GetFileTypes(uri, mimeTypeFilter, callingInfo);
224             }
225         }, "ArkUIPaBackendGetFileTypes");
226     return ret;
227 }
228 
OpenFile(const Uri & uri,const std::string & mode)229 int32_t PaBackend::OpenFile(const Uri& uri, const std::string& mode)
230 {
231     int32_t ret = 0;
232     CallingInfo callingInfo;
233     NAPI_RemoteObject_getCallingInfo(callingInfo);
234     CHECK_NULL_RETURN(jsBackendEngine_, ret);
235     jsBackendEngine_->PostSyncTask(
236         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, mode, callingInfo] {
237             auto jsBackendEngine = weakEngine.Upgrade();
238             if (jsBackendEngine != nullptr) {
239                 ret = jsBackendEngine->OpenFile(uri, mode, callingInfo);
240             }
241         }, "ArkUIPaBackendOpenFile");
242     return ret;
243 }
244 
OpenRawFile(const Uri & uri,const std::string & mode)245 int32_t PaBackend::OpenRawFile(const Uri& uri, const std::string& mode)
246 {
247     int32_t ret = 0;
248     CallingInfo callingInfo;
249     NAPI_RemoteObject_getCallingInfo(callingInfo);
250     CHECK_NULL_RETURN(jsBackendEngine_, ret);
251     jsBackendEngine_->PostSyncTask(
252         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, mode, callingInfo] {
253             auto jsBackendEngine = weakEngine.Upgrade();
254             if (jsBackendEngine != nullptr) {
255                 ret = jsBackendEngine->OpenRawFile(uri, mode, callingInfo);
256             }
257         }, "ArkUIPaBackendOpenRawFile");
258     return ret;
259 }
260 
NormalizeUri(const Uri & uri)261 Uri PaBackend::NormalizeUri(const Uri& uri)
262 {
263     Uri ret("");
264     CallingInfo callingInfo;
265     NAPI_RemoteObject_getCallingInfo(callingInfo);
266     CHECK_NULL_RETURN(jsBackendEngine_, ret);
267     jsBackendEngine_->PostSyncTask(
268         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, callingInfo] {
269             auto jsBackendEngine = weakEngine.Upgrade();
270             if (jsBackendEngine != nullptr) {
271                 ret = jsBackendEngine->NormalizeUri(uri, callingInfo);
272             }
273         }, "ArkUIPaBackendNormalizeUri");
274     return ret;
275 }
276 
DenormalizeUri(const Uri & uri)277 Uri PaBackend::DenormalizeUri(const Uri& uri)
278 {
279     Uri ret("");
280     CallingInfo callingInfo;
281     NAPI_RemoteObject_getCallingInfo(callingInfo);
282     CHECK_NULL_RETURN(jsBackendEngine_, ret);
283     jsBackendEngine_->PostSyncTask(
284         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, uri, callingInfo] {
285             auto jsBackendEngine = weakEngine.Upgrade();
286             if (jsBackendEngine != nullptr) {
287                 ret = jsBackendEngine->DenormalizeUri(uri, callingInfo);
288             }
289         }, "ArkUIPaBackendDenormalizeUri");
290     return ret;
291 }
292 
ParseManifest()293 void PaBackend::ParseManifest()
294 {
295     std::call_once(onceFlag_, [this]() {
296         std::string jsonContent;
297         if (!Framework::GetAssetContentImpl(assetManager_, PA_MANIFEST_JSON, jsonContent)) {
298             LOGE("RunPa parse manifest.json failed.");
299             EventReport::SendFormException(FormExcepType::RUN_PAGE_ERR);
300             return;
301         }
302 
303         if (manifestParser_ != nullptr) {
304             manifestParser_->Parse(jsonContent);
305         }
306     });
307 }
308 
LoadPa(const std::string & url,const OHOS::AAFwk::Want & want)309 void PaBackend::LoadPa(const std::string& url, const OHOS::AAFwk::Want& want)
310 {
311     CHECK_NULL_VOID(jsBackendEngine_);
312 
313     std::unique_lock<std::mutex> lock(LoadPaMutex_);
314     if (isStagingPageExist_) {
315         if (condition_.wait_for(lock, std::chrono::seconds(1)) == std::cv_status::timeout) {
316             LOGE("Load page failed, waiting for current page loading finish.");
317             return;
318         }
319     }
320 
321     isStagingPageExist_ = true;
322 
323     if (type_ == BackendType::FORM) {
324         jsBackendEngine_->PostSyncTask(
325             [weak = WeakPtr<JsBackendEngine>(jsBackendEngine_), url, want] {
326                 auto jsBackendEngine = weak.Upgrade();
327                 CHECK_NULL_VOID(jsBackendEngine);
328                 jsBackendEngine->LoadJs(url, want);
329             }, "ArkUIPaBackendFormLoadPa");
330     } else {
331         jsBackendEngine_->PostTask(
332             [weak = WeakPtr<JsBackendEngine>(jsBackendEngine_), url, want] {
333                 auto jsBackendEngine = weak.Upgrade();
334                 CHECK_NULL_VOID(jsBackendEngine);
335                 jsBackendEngine->LoadJs(url, want);
336             }, "ArkUIPaBackendLoadPa");
337     }
338 }
339 
RunPa(const std::string & url,const OHOS::AAFwk::Want & want)340 void PaBackend::RunPa(const std::string& url, const OHOS::AAFwk::Want& want)
341 {
342     ACE_SCOPED_TRACE("PaBackend::RunPa");
343     ParseManifest();
344     // if mutli pa in one hap should parse manifest get right url
345     LoadPa(url, want);
346 }
347 
OnCreate(const OHOS::AAFwk::Want & want)348 void PaBackend::OnCreate(const OHOS::AAFwk::Want& want)
349 {
350     CHECK_NULL_VOID(jsBackendEngine_);
351     jsBackendEngine_->PostSyncTask(
352         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), want] {
353             auto jsBackendEngine = weakEngine.Upgrade();
354             CHECK_NULL_VOID(jsBackendEngine);
355             jsBackendEngine->OnCreate(want);
356         }, "ArkUIPaBackendOnCreate");
357 }
358 
OnDelete(const int64_t formId)359 void PaBackend::OnDelete(const int64_t formId)
360 {
361     CHECK_NULL_VOID(jsBackendEngine_);
362     jsBackendEngine_->PostTask(
363         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), formId] {
364             auto jsBackendEngine = weakEngine.Upgrade();
365             CHECK_NULL_VOID(jsBackendEngine);
366             jsBackendEngine->OnDelete(formId);
367         }, "ArkUIPaBackendOnDelete");
368 }
369 
OnTriggerEvent(const int64_t formId,const std::string & message)370 void PaBackend::OnTriggerEvent(const int64_t formId, const std::string& message)
371 {
372     CHECK_NULL_VOID(jsBackendEngine_);
373     jsBackendEngine_->PostTask(
374         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), formId, message] {
375             auto jsBackendEngine = weakEngine.Upgrade();
376             CHECK_NULL_VOID(jsBackendEngine);
377             jsBackendEngine->OnTriggerEvent(formId, message);
378         }, "ArkUIPaBackendOnTriggerEvent");
379 }
380 
OnUpdate(const int64_t formId)381 void PaBackend::OnUpdate(const int64_t formId)
382 {
383     CHECK_NULL_VOID(jsBackendEngine_);
384     jsBackendEngine_->PostTask(
385         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), formId] {
386             auto jsBackendEngine = weakEngine.Upgrade();
387             CHECK_NULL_VOID(jsBackendEngine);
388             jsBackendEngine->OnUpdate(formId);
389         }, "ArkUIPaBackendOnUpdate");
390 }
391 
OnCastTemptoNormal(const int64_t formId)392 void PaBackend::OnCastTemptoNormal(const int64_t formId)
393 {
394     CHECK_NULL_VOID(jsBackendEngine_);
395     jsBackendEngine_->PostTask(
396         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), formId] {
397             auto jsBackendEngine = weakEngine.Upgrade();
398             CHECK_NULL_VOID(jsBackendEngine);
399             jsBackendEngine->OnCastTemptoNormal(formId);
400         }, "ArkUIPaBackendOnCastTempToNormal");
401 }
402 
OnVisibilityChanged(const std::map<int64_t,int32_t> & formEventsMap)403 void PaBackend::OnVisibilityChanged(const std::map<int64_t, int32_t>& formEventsMap)
404 {
405     CHECK_NULL_VOID(jsBackendEngine_);
406     jsBackendEngine_->PostTask(
407         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), formEventsMap] {
408             auto jsBackendEngine = weakEngine.Upgrade();
409             CHECK_NULL_VOID(jsBackendEngine);
410             jsBackendEngine->OnVisibilityChanged(formEventsMap);
411         }, "ArkUIPaBackendOnVisibilityChanged");
412 }
413 
OnAcquireFormState(const OHOS::AAFwk::Want & want)414 int32_t PaBackend::OnAcquireFormState(const OHOS::AAFwk::Want& want)
415 {
416     auto ret = (int32_t)AppExecFwk::FormState::UNKNOWN;
417     CHECK_NULL_RETURN(jsBackendEngine_, ret);
418     jsBackendEngine_->PostSyncTask(
419         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, want] {
420             auto jsBackendEngine = weakEngine.Upgrade();
421             if (jsBackendEngine != nullptr) {
422                 ret = jsBackendEngine->OnAcquireFormState(want);
423             }
424         }, "ArkUIPaBackendOnAcquireFormState");
425     return ret;
426 }
427 
OnConnect(const OHOS::AAFwk::Want & want)428 sptr<IRemoteObject> PaBackend::OnConnect(const OHOS::AAFwk::Want& want)
429 {
430     sptr<IRemoteObject> ret = nullptr;
431     CHECK_NULL_RETURN(jsBackendEngine_, ret);
432     jsBackendEngine_->PostSyncTask(
433         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &ret, want] {
434             auto jsBackendEngine = weakEngine.Upgrade();
435             if (jsBackendEngine != nullptr) {
436                 ret = jsBackendEngine->OnConnectService(want);
437             }
438         }, "ArkUIPaBackendConnectService");
439     return ret;
440 }
441 
OnDisConnect(const OHOS::AAFwk::Want & want)442 void PaBackend::OnDisConnect(const OHOS::AAFwk::Want& want)
443 {
444     CHECK_NULL_VOID(jsBackendEngine_);
445     jsBackendEngine_->PostTask(
446         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), want] {
447             auto jsBackendEngine = weakEngine.Upgrade();
448             CHECK_NULL_VOID(jsBackendEngine);
449             jsBackendEngine->OnDisconnectService(want);
450         }, "ArkUIPaBackendDisconnectService");
451 }
452 
OnShare(int64_t formId,OHOS::AAFwk::WantParams & wantParams)453 bool PaBackend::OnShare(int64_t formId, OHOS::AAFwk::WantParams& wantParams)
454 {
455     bool result = false;
456     CHECK_NULL_RETURN(jsBackendEngine_, result);
457     jsBackendEngine_->PostSyncTask(
458         [weakEngine = WeakPtr<JsBackendEngine>(jsBackendEngine_), &result, formId, &wantParams] {
459             auto jsBackendEngine = weakEngine.Upgrade();
460             if (jsBackendEngine != nullptr) {
461                 result = jsBackendEngine->OnShare(formId, wantParams);
462             }
463         }, "ArkUIPaBackendOnShare");
464     return result;
465 }
466 } // namespace OHOS::Ace
467