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