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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_COMMON_JS_ENGINE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_COMMON_JS_ENGINE_H
18 
19 #include <functional>
20 #include <set>
21 #include <string>
22 #include <memory>
23 #include <unordered_map>
24 
25 #include "base/utils/macros.h"
26 #include "core/common/frontend.h"
27 #include "core/common/js_message_dispatcher.h"
28 #include "frameworks/bridge/js_frontend/frontend_delegate.h"
29 
30 class NativeEngine;
31 class NativeReference;
32 typedef struct napi_value__* napi_value;
33 
34 namespace OHOS::Ace::Framework {
35 class JsAcePage;
36 using PixelMapNapiEntry = void* (*)(void*, void*);
37 struct JsModule {
38     const std::string moduleName;
39     const std::string methods;
40 };
41 
42 struct JsComponent {
43     const std::string componentName;
44     const std::string methods;
45 };
46 
47 class JsEngineInstance {
48 public:
49     JsEngineInstance() = default;
50     virtual ~JsEngineInstance() = default;
51 
52     virtual void FlushCommandBuffer(void* context, const std::string& command);
GetNativeEngine()53     NativeEngine* GetNativeEngine()
54     {
55         return nativeEngine_;
56     }
SetNativeEngine(NativeEngine * nativeEngine)57     void SetNativeEngine(NativeEngine* nativeEngine)
58     {
59         nativeEngine_ = nativeEngine;
60     }
61 
62 protected:
63     NativeEngine* nativeEngine_ = nullptr;
64 };
65 
66 using InspectorFunc = std::function<void()>;
67 class InspectorEvent : public virtual AceType {
DECLARE_ACE_TYPE(InspectorEvent,AceType)68     DECLARE_ACE_TYPE(InspectorEvent, AceType)
69 public:
70     explicit InspectorEvent(InspectorFunc&& callback) : callback_(std::move(callback)) {}
71     ~InspectorEvent() override = default;
72 
operator()73     void operator()() const
74     {
75         if (callback_) {
76             callback_();
77         }
78     }
79 
80 private:
81     InspectorFunc callback_;
82 };
83 
84 using PageUrlCheckFunc = std::function<void(const std::string&, const std::function<void()>&,
85     const std::function<void(int32_t, const std::string&)>&)>;
86 
87 class ACE_FORCE_EXPORT JsEngine : public AceType {
88     DECLARE_ACE_TYPE(JsEngine, AceType);
89 
90 public:
91     JsEngine() = default;
92     ~JsEngine() override = default;
93 
94     void RegisterSingleComponent(std::string& command, const std::string& componentName, const std::string& methods);
95 
96     void RegisterSingleModule(std::string& command, const std::string& moduleName, const std::string& methods);
97 
98     void RegisterModules(std::string& command);
99 
100     void RegisterComponents(std::string& command);
101 
102     // Initialize the JS engine.
103     virtual bool Initialize(const RefPtr<FrontendDelegate>& delegate) = 0;
104 
105     // Destroy the JS engine resource.
Destroy()106     virtual void Destroy() {}
107 
108     // Load script in JS engine, and execute in corresponding context.
109     virtual void LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage) = 0;
110     // Load ets card script in JS engine, and execute in corresponding context.
111     virtual bool LoadCard(const std::string& url, int64_t cardId, const std::string& entryPoint = "")
112     {
113         return false;
114     }
115 
116     // Load the app.js file of the FA model in NG structure..
LoadFaAppSource()117     virtual bool LoadFaAppSource()
118     {
119         return false;
120     }
121 
122     // Load the js file of the page in NG structure..
123     virtual bool LoadPageSource(
124         const std::string& /* url */, const std::function<void(const std::string&, int32_t)>& errorCallback = nullptr)
125     {
126         return false;
127     }
128 
129     virtual bool LoadPageSource(
130         const std::shared_ptr<std::vector<uint8_t>>& content,
131         const std::function<void(const std::string&, int32_t)>& errorCallback = nullptr,
132         const std::string& contentName = "")
133     {
134         return false;
135     }
136 
LoadNamedRouterSource(const std::string & namedRoute,bool isTriggeredByJs)137     virtual bool LoadNamedRouterSource(const std::string& namedRoute, bool isTriggeredByJs)
138     {
139         return false;
140     }
141 
GetFullPathInfo()142     virtual std::unique_ptr<JsonValue> GetFullPathInfo()
143     {
144         return nullptr;
145     }
146 
RestoreFullPathInfo(std::unique_ptr<JsonValue> namedRouterInfo)147     virtual void RestoreFullPathInfo(std::unique_ptr<JsonValue> namedRouterInfo) {}
148 
GetNamedRouterInfo()149     virtual std::unique_ptr<JsonValue> GetNamedRouterInfo()
150     {
151         return nullptr;
152     }
153 
RestoreNamedRouterInfo(std::unique_ptr<JsonValue> namedRouterInfo)154     virtual void RestoreNamedRouterInfo(std::unique_ptr<JsonValue> namedRouterInfo) {}
155 
IsNamedRouterNeedPreload(const std::string & name)156     virtual bool IsNamedRouterNeedPreload(const std::string& name)
157     {
158         return false;
159     }
160 
PreloadNamedRouter(const std::string & name,std::function<void (bool)> && loadFinishCallback)161     virtual void PreloadNamedRouter(const std::string& name, std::function<void(bool)>&& loadFinishCallback) {}
162 
SetPageUrlCheckFunc(PageUrlCheckFunc && func)163     virtual void SetPageUrlCheckFunc(PageUrlCheckFunc&& func)
164     {
165         pageUrlCheckFunc_ = func;
166     }
167 
SearchRouterRegisterMap(const std::string & pageName)168     virtual std::string SearchRouterRegisterMap(const std::string& pageName)
169     {
170         return "";
171     }
172 
LoadNavDestinationSource(const std::string & pageUrl,const std::string & bundleName,const std::string & moduleName,bool isSingleton)173     virtual int32_t LoadNavDestinationSource(const std::string& pageUrl, const std::string& bundleName,
174         const std::string& moduleName, bool isSingleton)
175     {
176         return false;
177     }
178 
UpdateRootComponent()179     virtual bool UpdateRootComponent()
180     {
181         return false;
182     }
183 
LoadPluginComponent(const std::string & url,const RefPtr<JsAcePage> & page,bool isMainPage)184     virtual bool LoadPluginComponent(const std::string &url, const RefPtr<JsAcePage>& page, bool isMainPage)
185     {
186         return false;
187     }
188 
ExecuteJs(const uint8_t * content,int32_t size)189     virtual bool ExecuteJs(const uint8_t* content, int32_t size)
190     {
191         return false;
192     }
193 
194     // Update running page
195     virtual void UpdateRunningPage(const RefPtr<JsAcePage>& page) = 0;
196 
197     // Update staging page
198     virtual void UpdateStagingPage(const RefPtr<JsAcePage>& page) = 0;
199 
200     // Reset loading page
201     virtual void ResetStagingPage() = 0;
202 
203     virtual void SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher) = 0;
204 
205     // Fire AsyncEvent on JS
206     virtual void FireAsyncEvent(const std::string& eventId, const std::string& param) = 0;
207 
208     // Fire SyncEvent on JS
209     virtual void FireSyncEvent(const std::string& eventId, const std::string& param) = 0;
210 
211     // Fire external event on JS thread
212     virtual void FireExternalEvent(const std::string& componentId, uint32_t nodeId, bool isDestroy = false) = 0;
213 
214     // Timer callback on JS
215     virtual void TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval) = 0;
216 
217     // Destroy page instance on JS
218     virtual void DestroyPageInstance(int32_t pageId) = 0;
219 
220     // destroy application instance according packageName
221     virtual void DestroyApplication(const std::string& packageName) = 0;
222 
223     // update application State according packageName
UpdateApplicationState(const std::string & packageName,Frontend::State state)224     virtual void UpdateApplicationState(const std::string& packageName, Frontend::State state) {}
225 
OnWindowDisplayModeChanged(bool isShownInMultiWindow,const std::string & data)226     virtual void OnWindowDisplayModeChanged(bool isShownInMultiWindow, const std::string& data) {}
227 
OnNewWant(const std::string & data)228     virtual void OnNewWant(const std::string& data) {}
229 
OnSaveAbilityState(std::string & data)230     virtual void OnSaveAbilityState(std::string& data) {}
231 
OnRestoreAbilityState(const std::string & data)232     virtual void OnRestoreAbilityState(const std::string& data) {}
233 
OnConfigurationUpdated(const std::string & data)234     virtual void OnConfigurationUpdated(const std::string& data) {}
235 
OnActive()236     virtual void OnActive() {}
237 
OnInactive()238     virtual void OnInactive() {}
239 
OnMemoryLevel(const int32_t code)240     virtual void OnMemoryLevel(const int32_t code) {}
241 
OnStartContinuation()242     virtual bool OnStartContinuation()
243     {
244         return false;
245     }
246 
OnCompleteContinuation(int32_t code)247     virtual void OnCompleteContinuation(int32_t code) {}
248 
OnRemoteTerminated()249     virtual void OnRemoteTerminated() {}
250 
OnSaveData(std::string & data)251     virtual void OnSaveData(std::string& data) {}
252 
OnRestoreData(const std::string & data)253     virtual bool OnRestoreData(const std::string& data)
254     {
255         return false;
256     }
257 
MediaQueryCallback(const std::string & callbackId,const std::string & args)258     virtual void MediaQueryCallback(const std::string& callbackId, const std::string& args)
259     {
260         if (mediaUpdateCallback_) {
261             mediaUpdateCallback_(this);
262         }
263     }
264 
LayoutInspectorCallback(const std::string & componentId)265     void LayoutInspectorCallback(const std::string& componentId)
266     {
267         auto iter = layoutEvents_.find(componentId);
268         if (iter != layoutEvents_.end()) {
269             for (auto&& observer : iter->second) {
270                 (*observer)();
271             }
272         }
273     }
274 
DrawInspectorCallback(const std::string & componentId)275     void DrawInspectorCallback(const std::string& componentId)
276     {
277         auto iter = drawEvents_.find(componentId);
278         if (iter != drawEvents_.end()) {
279             for (auto&& observer : iter->second) {
280                 (*observer)();
281             }
282         }
283     }
284 
285     virtual void RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp) = 0;
286 
287     virtual void JsCallback(const std::string& callbackId, const std::string& args) = 0;
288 
SetErrorEventHandler(std::function<void (const std::string &,const std::string &)> && errorCallback)289     virtual void SetErrorEventHandler(std::function<void(const std::string&, const std::string&)>&& errorCallback) {}
290 
291     virtual void RunGarbageCollection() = 0;
292 
RunFullGarbageCollection()293     virtual void RunFullGarbageCollection() {}
294 
DumpHeapSnapshot(bool isPrivate)295     virtual void DumpHeapSnapshot(bool isPrivate) {}
296 
DestroyHeapProfiler()297     virtual void DestroyHeapProfiler() {}
298 
ForceFullGC()299     virtual void ForceFullGC() {}
300 
NotifyUIIdle()301     virtual void NotifyUIIdle() {}
302 
GetStacktraceMessage()303     virtual std::string GetStacktraceMessage()
304     {
305         return "";
306     }
307 
GetStackTrace(std::string & trace)308     virtual void GetStackTrace(std::string& trace) {}
309 
NotifyAppStorage(const std::string & key,const std::string & value)310     virtual void NotifyAppStorage(const std::string& key, const std::string& value) {}
311 
312     virtual RefPtr<GroupJsBridge> GetGroupJsBridge() = 0;
313 
GetFrontend()314     virtual ACE_EXPORT RefPtr<FrontendDelegate> GetFrontend()
315     {
316         return nullptr;
317     }
318 
SetLocalStorage(int32_t instanceId,NativeReference * storage)319     virtual void SetLocalStorage(int32_t instanceId, NativeReference* storage) {}
320 
SetContext(int32_t instanceId,NativeReference * context)321     virtual void SetContext(int32_t instanceId, NativeReference* context) {}
322 
SetPkgNameList(const std::map<std::string,std::string> & map)323     virtual void SetPkgNameList(const std::map<std::string, std::string>& map) {}
324 
SetPkgAliasList(const std::map<std::string,std::string> & map)325     virtual void SetPkgAliasList(const std::map<std::string, std::string>& map) {}
326 
SetpkgContextInfoList(const std::map<std::string,std::vector<std::vector<std::string>>> & map)327     virtual void SetpkgContextInfoList(const std::map<std::string, std::vector<std::vector<std::string>>>& map) {}
328 
IsDebugVersion()329     bool IsDebugVersion() const
330     {
331         return isDebugVersion_;
332     }
333 
SetDebugVersion(bool value)334     void SetDebugVersion(bool value)
335     {
336         isDebugVersion_ = value;
337     }
338 
NeedDebugBreakPoint()339     bool NeedDebugBreakPoint() const
340     {
341         return needDebugBreakPoint_;
342     }
343 
SetNeedDebugBreakPoint(bool value)344     void SetNeedDebugBreakPoint(bool value)
345     {
346         needDebugBreakPoint_ = value;
347     }
348 
GetInstanceName()349     const std::string& GetInstanceName() const
350     {
351         return instanceName_;
352     }
353 
SetInstanceName(const std::string & name)354     void SetInstanceName(const std::string& name)
355     {
356         instanceName_ = name;
357     }
358 
AddExtraNativeObject(const std::string & key,void * value)359     void AddExtraNativeObject(const std::string& key, void* value)
360     {
361         extraNativeObject_[key] = value;
362     }
363 
GetExtraNativeObject()364     const std::unordered_map<std::string, void*>& GetExtraNativeObject() const
365     {
366         return extraNativeObject_;
367     }
368 
SetForceUpdate(bool needUpdate)369     void SetForceUpdate(bool needUpdate)
370     {
371         needUpdate_ = needUpdate;
372     }
373 
GetNativeEngine()374     NativeEngine* GetNativeEngine()
375     {
376         return nativeEngine_;
377     }
378 
RegisterMediaUpdateCallback(std::function<void (JsEngine *)> cb)379     void ACE_EXPORT RegisterMediaUpdateCallback(std::function<void(JsEngine*)> cb)
380     {
381         mediaUpdateCallback_ = std::move(cb);
382     }
383 
UnregisterMediaUpdateCallback()384     void ACE_EXPORT UnregisterMediaUpdateCallback()
385     {
386         mediaUpdateCallback_ = nullptr;
387     }
388 
RegisterLayoutInspectorCallback(const RefPtr<InspectorEvent> & layoutEvent,const std::string & componentId)389     void ACE_EXPORT RegisterLayoutInspectorCallback(
390         const RefPtr<InspectorEvent>& layoutEvent, const std::string& componentId)
391     {
392         layoutEvents_[componentId].emplace(layoutEvent);
393     }
394 
UnregisterLayoutInspectorCallback(const RefPtr<InspectorEvent> & layoutEvent,const std::string & componentId)395     void ACE_EXPORT UnregisterLayoutInspectorCallback(
396         const RefPtr<InspectorEvent>& layoutEvent, const std::string& componentId)
397     {
398         auto iter = layoutEvents_.find(componentId);
399         if (iter != layoutEvents_.end()) {
400             iter->second.erase(layoutEvent);
401             if (iter->second.empty()) {
402                 layoutEvents_.erase(componentId);
403             }
404         }
405     }
406 
RegisterDrawInspectorCallback(const RefPtr<InspectorEvent> & drawEvent,const std::string & componentId)407     void ACE_EXPORT RegisterDrawInspectorCallback(
408         const RefPtr<InspectorEvent>& drawEvent, const std::string& componentId)
409     {
410         drawEvents_[componentId].emplace(drawEvent);
411     }
412 
UnregisterDrawInspectorCallback(const RefPtr<InspectorEvent> & drawEvent,const std::string & componentId)413     void ACE_EXPORT UnregisterDrawInspectorCallback(
414         const RefPtr<InspectorEvent>& drawEvent, const std::string& componentId)
415     {
416         auto iter = drawEvents_.find(componentId);
417         if (iter != drawEvents_.end()) {
418             iter->second.erase(drawEvent);
419             if (iter->second.empty()) {
420                 drawEvents_.erase(componentId);
421             }
422         }
423     }
424 
IsLayoutCallBackFuncExist(const std::string & componentId)425     bool IsLayoutCallBackFuncExist(const std::string& componentId) const
426     {
427         if (layoutEvents_.find(componentId) != layoutEvents_.end()) {
428             return true;
429         }
430         return false;
431     }
432 
IsDrawCallBackFuncExist(const std::string & componentId)433     bool IsDrawCallBackFuncExist(const std::string& componentId) const
434     {
435         if (drawEvents_.find(componentId) != drawEvents_.end()) {
436             return true;
437         }
438         return false;
439     }
440 
441     virtual void RunNativeEngineLoop();
442 
SetPluginBundleName(const std::string & pluginBundleName)443     virtual void SetPluginBundleName(const std::string& pluginBundleName) {}
444 
SetPluginModuleName(const std::string & pluginModuleName)445     virtual void SetPluginModuleName(const std::string& pluginModuleName) {}
446 
447 #if !defined(PREVIEW)
448     static PixelMapNapiEntry GetPixelMapNapiEntry();
449 #endif
450 #if defined(PREVIEW)
GetNewComponentWithJsCode(const std::string & jsCode,const std::string & viewID)451     virtual RefPtr<Component> GetNewComponentWithJsCode(const std::string& jsCode, const std::string& viewID)
452     {
453         return nullptr;
454     }
455 
ExecuteJsForFastPreview(const std::string & jsCode,const std::string & viewID)456     virtual bool ExecuteJsForFastPreview(const std::string& jsCode, const std::string& viewID)
457     {
458         return true;
459     }
460 
ReplaceJSContent(const std::string & url,const std::string componentName)461     virtual void ReplaceJSContent(const std::string& url, const std::string componentName)
462     {
463         LOGE("Ark does not support replaceJSContent");
464         return;
465     }
466 
InitializeModuleSearcher(const std::string & bundleName,const std::string & moduleName,const std::string assetPath,bool isBundle)467     virtual void InitializeModuleSearcher(
468         const std::string& bundleName, const std::string& moduleName, const std::string assetPath, bool isBundle)
469     {
470         LOGE("Ark does not support InitializeModuleSearcher");
471     }
472 
IsComponentPreview()473     virtual bool IsComponentPreview()
474     {
475         return false;
476     }
477 #endif
FlushReload()478     virtual void FlushReload() {}
GetContextValue()479     virtual napi_value GetContextValue()
480     {
481         napi_value value = nullptr;
482         return value;
483     }
484 
GetFrameNodeValueByNodeId(int32_t nodeId)485     virtual napi_value GetFrameNodeValueByNodeId(int32_t nodeId)
486     {
487         return nullptr;
488     }
489 
490 protected:
491     NativeEngine* nativeEngine_ = nullptr;
492     std::function<void(JsEngine*)> mediaUpdateCallback_;
493     std::map<std::string, std::set<RefPtr<InspectorEvent>>> layoutEvents_;
494     std::map<std::string, std::set<RefPtr<InspectorEvent>>> drawEvents_;
495     bool needUpdate_ = false;
496     PageUrlCheckFunc pageUrlCheckFunc_;
497 
498 private:
499     // weather the app has debugger.so.
500     bool isDebugVersion_ = false;
501 
502     // if debug, '-D' means need debug breakpoint, by default, do not enter breakpoint.
503     bool needDebugBreakPoint_ = false;
504 
505     std::string instanceName_;
506 
507     std::unordered_map<std::string, void*> extraNativeObject_;
508 };
509 } // namespace OHOS::Ace::Framework
510 #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_COMMON_JS_ENGINE_H
511