• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_V8_V8_ENGINE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_V8_V8_ENGINE_H
18 
19 #include <memory>
20 #include <mutex>
21 #include <string>
22 #include <vector>
23 
24 #include "third_party/v8/include/libplatform/libplatform.h"
25 #include "third_party/v8/include/v8.h"
26 
27 #include "base/memory/ace_type.h"
28 #include "base/utils/noncopyable.h"
29 #include "core/common/ace_application_info.h"
30 #include "core/common/ace_page.h"
31 #include "frameworks/bridge/js_frontend/engine/common/js_engine.h"
32 #include "frameworks/bridge/js_frontend/js_ace_page.h"
33 #include "native_engine/impl/v8/v8_native_engine.h"
34 
35 namespace OHOS::Ace::Framework {
36 
37 class V8EngineInstance final : public AceType, public JsEngineInstance {
38 public:
39     enum IsolateData {
40         FRONTEND_DELEGATE = 0,
41         RUNNING_PAGE = 1,
42         STAGING_PAGE = 2,
43         DISPATCHER = 3,
44     };
45 
46     static void CallJs(v8::Isolate* isolate,
47         v8::Persistent<v8::Context, v8::CopyablePersistentTraits<v8::Context>> pcontext, const std::string& callbackId,
48         const std::string& args, bool keepAlive = false, bool isGlobal = false);
49 
V8EngineInstance(const RefPtr<FrontendDelegate> & delegate,int32_t instanceId)50     explicit V8EngineInstance(const RefPtr<FrontendDelegate>& delegate, int32_t instanceId)
51         : frontendDelegate_(delegate), instanceId_(instanceId)
52     {}
53     ~V8EngineInstance() override;
54 
55     void FlushCommandBuffer(void* context, const std::string& command) override;
56 
57     bool InitJsEnv();
58 
59     void InitJsConsoleObject(v8::Local<v8::Context>& context, v8::Isolate* isolate);
60     void InitJsDocumentObject(v8::Local<v8::Context>& context, v8::Isolate* isolate);
61 
62     void InitJsPerfUtilObject(v8::Local<v8::Context>& context);
63 
64     void InitJsContext();
65 
66     void InitGlobalObjectTemplate();
67 
68     void CallJs(const std::string& callbackId, const std::string& args, bool keepAlive = false, bool isGlobal = false);
69 
GetV8Isolate()70     v8::Isolate* GetV8Isolate() const
71     {
72         return isolate_;
73     }
74 
GetV8Context()75     v8::Local<v8::Context> GetV8Context() const
76     {
77         return context_.Get(isolate_);
78     }
79 
GetContext()80     v8::Persistent<v8::Context>& GetContext()
81     {
82         return context_;
83     }
84 
85     bool FireJsEvent(const std::string& param);
86 
SetRunningPage(const RefPtr<JsAcePage> & page)87     void SetRunningPage(const RefPtr<JsAcePage>& page)
88     {
89         std::lock_guard<std::mutex> lock(mutex_);
90         runningPage_ = page;
91         isolate_->SetData(RUNNING_PAGE, static_cast<void*>(&runningPage_));
92     }
93 
GetRunningPage()94     RefPtr<JsAcePage> GetRunningPage() const
95     {
96         std::lock_guard<std::mutex> lock(mutex_);
97         return runningPage_;
98     }
99 
SetStagingPage(const RefPtr<JsAcePage> & page)100     void SetStagingPage(const RefPtr<JsAcePage>& page)
101     {
102         std::lock_guard<std::mutex> lock(mutex_);
103         stagingPage_ = page;
104         isolate_->SetData(STAGING_PAGE, static_cast<void*>(&stagingPage_));
105     }
106 
GetStagingPage()107     RefPtr<JsAcePage> GetStagingPage() const
108     {
109         std::lock_guard<std::mutex> lock(mutex_);
110         return stagingPage_;
111     }
112 
ResetStagingPage(const RefPtr<JsAcePage> & page)113     void ResetStagingPage(const RefPtr<JsAcePage>& page)
114     {
115         stagingPage_ = page;
116         isolate_->SetData(STAGING_PAGE, static_cast<void*>(&stagingPage_));
117     }
118 
SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher> & dispatcher)119     void SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher)
120     {
121         dispatcher_ = dispatcher;
122         isolate_->SetData(DISPATCHER, static_cast<void*>(&dispatcher_));
123     }
124 
GetJsMessageDispatcher()125     WeakPtr<JsMessageDispatcher> GetJsMessageDispatcher() const
126     {
127         return dispatcher_;
128     }
129 
GetInstanceId()130     int32_t GetInstanceId() const
131     {
132         return instanceId_;
133     }
134 
GetDelegate()135     RefPtr<FrontendDelegate> GetDelegate() const
136     {
137         return frontendDelegate_;
138     }
139 
SetV8NativeEngine(std::shared_ptr<V8NativeEngine> nativeEngine)140     void SetV8NativeEngine(std::shared_ptr<V8NativeEngine> nativeEngine)
141     {
142         nativeEngine_ = nativeEngine;
143     }
144 
GetV8NativeEngine()145     std::shared_ptr<V8NativeEngine> GetV8NativeEngine() const
146     {
147         return nativeEngine_.lock();
148     }
149 
150 private:
151     v8::Isolate* isolate_ = nullptr;
152     v8::Isolate::CreateParams create_params_;
153     v8::Persistent<v8::Context> context_;
154     v8::Persistent<v8::ObjectTemplate> globalObjectTemplate_;
155     RefPtr<FrontendDelegate> frontendDelegate_;
156     int32_t instanceId_ = 0;
157 
158     // runningPage_ is the page that is loaded and rendered successfully, while stagingPage_ is to
159     // handle all page routing situation, which include two stages:
160     // - Loading stage: when a new page is loaded by qjs engine but not rendered, stagingPage_ point to
161     //   a new created page, which is different with runningPage_, the DOM build operations should call
162     //   this one, such as domCreateBody, domAddElement.
163     // - Running stage: If the stagingPage_ rendered successfully, the runningPage_ will update to stagingPage_.
164     //   If the stagingPage_ render failed, it will reset to runningPage_. So in running stage, runningPage_
165     //   and stagingPage_ point to the same page. But it's better to use runningPage_ in dom update tasks,
166     //   such as removeElement, updateElementAttrs and updateElementStyles.
167     RefPtr<JsAcePage> runningPage_;
168     RefPtr<JsAcePage> stagingPage_;
169 
170     WeakPtr<JsMessageDispatcher> dispatcher_;
171     std::weak_ptr<V8NativeEngine> nativeEngine_;
172     mutable std::mutex mutex_;
173 
174     ACE_DISALLOW_COPY_AND_MOVE(V8EngineInstance);
175 };
176 
177 class V8Engine : public JsEngine {
178 public:
179     explicit V8Engine(int32_t instanceId);
180     ~V8Engine() override;
181 
182     bool Initialize(const RefPtr<FrontendDelegate>& delegate) override;
183 
184     // Load and initialize a JS bundle into the JS Framework
185     void LoadJs(const std::string& url, const RefPtr<JsAcePage>& page, bool isMainPage) override;
186 
187     // Update running page
188     void UpdateRunningPage(const RefPtr<JsAcePage>& page) override;
189 
190     // Update staging page
191     void UpdateStagingPage(const RefPtr<JsAcePage>& page) override;
192 
193     // Reset staging page
194     void ResetStagingPage() override;
195 
196     void SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher) override;
197 
198     // Fire AsyncEvent on JS
199     void FireAsyncEvent(const std::string& eventId, const std::string& param) override;
200 
201     // Fire SyncEvent on JS
202     void FireSyncEvent(const std::string& eventId, const std::string& param) override;
203 
204     // Fire external event on JS thread
205     void FireExternalEvent(const std::string& componentId, const uint32_t nodeId, const bool isDestroy) override;
206 
207     // Timer callback
208     void TimerCallback(const std::string& callbackId, const std::string& delay, bool isInterval) override;
209 
210     // Destroy page instance
211     void DestroyPageInstance(int32_t pageId) override;
212 
213     // Destroy application instance according to packageName
DestroyApplication(const std::string & packageName)214     void DestroyApplication(const std::string& packageName) override {}
215 
216     void UpdateApplicationState(const std::string& packageName, Frontend::State state) override;
217 
218     void MediaQueryCallback(const std::string& callbackId, const std::string& args) override;
219 
220     void RequestAnimationCallback(const std::string& callbackId, uint64_t timeStamp) override;
221 
222     void JsCallback(const std::string& callbackId, const std::string& args) override;
223 
224     void RunGarbageCollection() override;
225 
226     RefPtr<GroupJsBridge> GetGroupJsBridge() override;
227 
GetFrontend()228     FrontendDelegate* GetFrontend() override
229     {
230         return AceType::RawPtr(engineInstance_->GetDelegate());
231     }
232 
233     static std::unique_ptr<v8::Platform>& GetPlatform();
234 
235 private:
236     void GetLoadOptions(std::string& optionStr, bool isMainPage, const RefPtr<JsAcePage>& page);
237     void RegisterWorker();
238     void RegisterInitWorkerFunc();
239     void RegisterAssetFunc();
240     void RegisterOffWorkerFunc();
241     void SetPostTask();
242 
243     RefPtr<V8EngineInstance> engineInstance_;
244     int32_t instanceId_ = 0;
245     std::shared_ptr<V8NativeEngine> nativeEngine_;
246 
247     ACE_DISALLOW_COPY_AND_MOVE(V8Engine);
248 };
249 
250 } // namespace OHOS::Ace::Framework
251 
252 #endif // FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_ENGINE_V8_V8_ENGINE_H
253