* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_FRONTEND_DELEGATE_IMPL_H
#define FOUNDATION_ACE_FRAMEWORKS_BRIDGE_JS_FRONTEND_FRONTEND_DELEGATE_IMPL_H
#include <future>
#include <mutex>
#include <unordered_map>
#include "base/memory/ace_type.h"
#include "base/thread/cancelable_callback.h"
#include "base/utils/measure_util.h"
#include "core/common/frontend.h"
#include "core/common/js_message_dispatcher.h"
#include "core/components/dialog/dialog_component.h"
#include "core/pipeline/pipeline_base.h"
#include "frameworks/bridge/common/accessibility/accessibility_node_manager.h"
#include "frameworks/bridge/common/manifest/manifest_parser.h"
#include "frameworks/bridge/common/utils/pipeline_context_holder.h"
#include "frameworks/bridge/js_frontend/engine/common/group_js_bridge.h"
#include "frameworks/bridge/js_frontend/frontend_delegate.h"
#include "frameworks/bridge/js_frontend/js_ace_page.h"
namespace OHOS::Ace::Framework {
using LoadJsCallback = std::function<void(const std::string&, const RefPtr<JsAcePage>&, bool isMainPage)>;
using JsMessageDispatcherSetterCallback = std::function<void(const RefPtr<JsMessageDispatcher>&)>;
using EventCallback = std::function<void(const std::string&, const std::string&)>;
using ExternalEventCallback = std::function<void(const std::string&, const uint32_t&, const bool&)>;
using UpdatePageCallback = std::function<void(const RefPtr<JsAcePage>&)>;
using ResetStagingPageCallback = std::function<void()>;
using MediaQueryCallback = std::function<void(const std::string& callbackId, const std::string& args)>;
using LayoutInspectorCallback = std::function<void(const std::string& componedId)>;
using DrawInspectorCallback = std::function<void(const std::string& componedId)>;
using DrawChildrenInspectorCallback = std::function<void(const std::string& componedId,
const std::vector<int32_t>& childIds)>;
using LayoutChildrenInspectorCallback = std::function<void(const std::string& componedId)>;
using IsDrawChildrenCallbackFuncExistCallback = std::function<bool(const std::string& componedId)>;
using IsLayoutChildrenCallbackFuncExistCallback = std::function<bool(const std::string& componedId)>;
using LayoutInspectorUniqueIdCallback = std::function<void(int32_t uniqueId)>;
using DrawInspectorUniqueIdCallback = std::function<void(int32_t uniqueId)>;
using DrawChildrenInspectorUniqueIdCallback = std::function<void(int32_t uniqueId)>;
using LayoutChildrenInspectorUniqueIdCallback = std::function<void(int32_t uniqueId)>;
using IsDrawChildrenCallbackFuncExistUniqueIdCallback = std::function<bool(int32_t uniqueId)>;
using IsLayoutChildrenCallbackFuncExistUniqueIdCallback = std::function<bool(int32_t uniqueId)>;
using DestroyPageCallback = std::function<void(int32_t pageId)>;
using DestroyApplicationCallback = std::function<void(const std::string& packageName)>;
using UpdateApplicationStateCallback = std::function<void(const std::string& packageName, Frontend::State state)>;
using TimerCallback = std::function<void(const std::string& callbackId, const std::string& delay, bool isInterval)>;
using RequestAnimationCallback = std::function<void(const std::string& callbackId, uint64_t timeStamp)>;
using JsCallback = std::function<void(const std::string& callbackId, const std::string& args)>;
using OnWindowDisplayModeChangedCallBack = std::function<void(bool isShownInMultiWindow, const std::string& data)>;
using OnConfigurationUpdatedCallBack = std::function<void(const std::string& data)>;
using OnNewWantCallBack = std::function<void(const std::string& data)>;
using OnSaveAbilityStateCallBack = std::function<void(std::string& data)>;
using OnRestoreAbilityStateCallBack = std::function<void(const std::string& data)>;
using OnActiveCallBack = std::function<void()>;
using OnInactiveCallBack = std::function<void()>;
using OnMemoryLevelCallBack = std::function<void(const int32_t level)>;
using OnStartContinuationCallBack = std::function<bool(void)>;
using OnCompleteContinuationCallBack = std::function<void(int32_t code)>;
using OnRemoteTerminatedCallBack = std::function<void(void)>;
using OnSaveDataCallBack = std::function<void(std::string& data)>;
using OnRestoreDataCallBack = std::function<bool(const std::string& data)>;
using CallNativeHandlerCallback = std::function<void(const std::string& event, const std::string& params)>;
using OnDigitalCrownCallback = std::function<bool(const std::string& callbackId, const std::string& args)>;
struct PageInfo {
int32_t pageId = -1;
std::string url;
bool isRestore = false;
std::function<void(int32_t)> alertCallback;
DialogProperties dialogProperties;
};
struct FrontendDelegateImplBuilder {
RefPtr<TaskExecutor> taskExecutor;
LoadJsCallback loadCallback;
JsMessageDispatcherSetterCallback transferCallback;
EventCallback asyncEventCallback;
EventCallback syncEventCallback;
ExternalEventCallback externalEventCallback;
UpdatePageCallback updatePageCallback;
ResetStagingPageCallback resetStagingPageCallback;
DestroyPageCallback destroyPageCallback;
DestroyApplicationCallback destroyApplicationCallback;
UpdateApplicationStateCallback updateApplicationStateCallback;
OnStartContinuationCallBack onStartContinuationCallBack;
OnCompleteContinuationCallBack onCompleteContinuationCallBack;
OnRemoteTerminatedCallBack onRemoteTerminatedCallBack;
OnSaveDataCallBack onSaveDataCallBack;
OnRestoreDataCallBack onRestoreDataCallBack;
TimerCallback timerCallback;
MediaQueryCallback mediaQueryCallback;
RequestAnimationCallback requestAnimationCallback;
JsCallback jsCallback;
OnWindowDisplayModeChangedCallBack onWindowDisplayModeChangedCallBack;
OnNewWantCallBack onNewWantCallBack;
OnSaveAbilityStateCallBack onSaveAbilityStateCallBack;
OnRestoreAbilityStateCallBack onRestoreAbilityStateCallBack;
OnActiveCallBack onActiveCallBack;
OnInactiveCallBack onInactiveCallBack;
OnMemoryLevelCallBack onMemoryLevelCallBack;
CallNativeHandlerCallback callNativeHandler;
OnDigitalCrownCallback onCrownEventCallback;
void* ability;
};
class DelegateClient {
public:
using RouterPushCallback = std::function<void(const std::string& url)>;
using GetWebPageUrlCallback = std::function<void(std::string& url, int32_t& id)>;
using IsPagePathInvalidCallback = std::function<void(bool& isPageInvalid)>;
DelegateClient &operator = (const DelegateClient &) = delete;
DelegateClient(const DelegateClient &) = delete;
~DelegateClient() = default;
static DelegateClient& GetInstance()
{
static DelegateClient instance;
return instance;
}
void RegisterRouterPushCallback(RouterPushCallback &&callback)
{
routerPushCallback_ = callback;
}
void RouterPush(const std::string& url)
{
if (routerPushCallback_) {
return routerPushCallback_(url);
}
}
void RegisterGetWebPageUrlCallback(GetWebPageUrlCallback &&callback)
{
getWebPageUrlCallback_ = callback;
}
void GetWebPageUrl(std::string& pageUrl, int32_t& pageId)
{
if (getWebPageUrlCallback_) {
return getWebPageUrlCallback_(pageUrl, pageId);
}
}
void RegisterIsPagePathInvalidCallback(IsPagePathInvalidCallback &&callback)
{
isPagePathInvalidCallback_ = callback;
}
void GetIsPagePathInvalid(bool& isPageInvalid)
{
if (isPagePathInvalidCallback_) {
return isPagePathInvalidCallback_(isPageInvalid);
}
}
private:
DelegateClient() = default;
RouterPushCallback routerPushCallback_;
GetWebPageUrlCallback getWebPageUrlCallback_;
IsPagePathInvalidCallback isPagePathInvalidCallback_;
};
class FrontendDelegateImpl : public FrontendDelegate {
DECLARE_ACE_TYPE(FrontendDelegateImpl, FrontendDelegate);
public:
explicit FrontendDelegateImpl(const FrontendDelegateImplBuilder& builder);
~FrontendDelegateImpl() override;
void AttachPipelineContext(const RefPtr<PipelineBase>& context) override;
UIContentErrorCode RunPage(const std::string& url, const std::string& params);
void SetJsMessageDispatcher(const RefPtr<JsMessageDispatcher>& dispatcher) const;
void TransferComponentResponseData(int32_t callbackId, int32_t code, std::vector<uint8_t>&& data);
void TransferJsResponseData(int32_t callbackId, int32_t code, std::vector<uint8_t>&& data) const;
#if defined(PREVIEW)
void TransferJsResponseDataPreview(int32_t callbackId, int32_t code, ResponseData responseData) const;
#endif
void TransferJsPluginGetError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const;
void TransferJsEventData(int32_t callbackId, int32_t code, std::vector<uint8_t>&& data) const;
void LoadPluginJsCode(std::string&& jsCode) const;
void LoadPluginJsByteCode(std::vector<uint8_t>&& jsCode, std::vector<int32_t>&& jsCodeLen) const;
void OnJsCallback(const std::string& callbackId, const std::string& data);
bool OnPageBackPress();
void OnBackGround();
void OnForeground();
void OnConfigurationUpdated(const std::string& configurationData);
void OnActive();
void OnInactive();
bool OnStartContinuation();
void OnCompleteContinuation(int32_t code);
void OnRemoteTerminated();
void OnSaveData(std::string& data);
bool OnRestoreData(const std::string& data);
void OnNewRequest(const std::string& data);
void OnMemoryLevel(const int32_t level);
void OnNewWant(const std::string& data);
void CallPopPage();
void OnApplicationDestroy(const std::string& packageName);
void OnApplicationUpdateState(const std::string& packageName, Frontend::State state);
void SetColorMode(ColorMode colorMode);
RefPtr<Framework::AccessibilityNodeManager> GetJsAccessibilityManager() const
{
return jsAccessibilityManager_;
}
void FireAccessibilityEvent(const AccessibilityEvent& accessibilityEvent);
void InitializeAccessibilityCallback();
void OnMediaQueryUpdate(bool isSynchronous = false) override;
void OnSurfaceChanged();
void OnLayoutCompleted(const std::string& componentId);
void OnDrawCompleted(const std::string& componentId);
void OnDrawChildrenCompleted(const std::string& componentId, const std::vector<int32_t>& childIds);
bool IsDrawChildrenCallbackFuncExist(const std::string& componentId);
void FireAsyncEvent(const std::string& eventId, const std::string& param, const std::string& jsonArgs);
bool FireSyncEvent(const std::string& eventId, const std::string& param, const std::string& jsonArgs);
void FireSyncEvent(
const std::string& eventId, const std::string& param, const std::string& jsonArgs, std::string& result);
void FireExternalEvent(
const std::string& eventId, const std::string& componentId, const uint32_t nodeId, const bool isDestroy);
void Push(const std::string& uri, const std::string& params) override;
void PushWithCallback(const std::string& uri, const std::string& params, bool recoverable,
const std::function<void(const std::string&, int32_t)>& errorCallback, uint32_t routerMode = 0) override;
void Replace(const std::string& uri, const std::string& params) override;
void ReplaceWithCallback(const std::string& uri, const std::string& params, bool recoverable,
const std::function<void(const std::string&, int32_t)>& errorCallback, uint32_t routerMode = 0) override;
void Back(const std::string& uri, const std::string& params) override;
void PostponePageTransition() override;
void LaunchPageTransition() override;
void Clear() override;
int32_t GetStackSize() const override;
void GetState(int32_t& index, std::string& name, std::string& path) override;
size_t GetComponentsCount() override;
std::string GetParams() override;
void TriggerPageUpdate(int32_t pageId, bool directExecute = false) override;
void PostJsTask(std::function<void()>&& task, const std::string& name) override;
void PostUITask(std::function<void()>&& task, const std::string& name) override;
const std::string& GetAppID() const override;
const std::string& GetAppName() const override;
const std::string& GetVersionName() const override;
int32_t GetVersionCode() const override;
WindowConfig& GetWindowConfig();
int32_t GetMinPlatformVersion() override;
bool IsUseLiteStyle();
bool IsWebFeature();
double MeasureText(MeasureContext context) override;
Size MeasureTextSize(MeasureContext context) override;
void ShowToast(const NG::ToastInfo& toastInfo, std::function<void(int32_t)>&& callback) override;
void ShowDialog(const std::string& title, const std::string& message, const std::vector<ButtonInfo>& buttons,
bool autoCancel, std::function<void(int32_t, int32_t)>&& callback,
const std::set<std::string>& callbacks) override;
void ShowDialog(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons,
std::function<void(int32_t, int32_t)>&& callback, const std::set<std::string>& callbacks) override;
void EnableAlertBeforeBackPage(const std::string& message, std::function<void(int32_t)>&& callback) override;
void DisableAlertBeforeBackPage() override;
void ShowActionMenu(const std::string& title, const std::vector<ButtonInfo>& button,
std::function<void(int32_t, int32_t)>&& callback) override;
void ShowActionMenu(const PromptDialogAttr& dialogAttr, const std::vector<ButtonInfo>& buttons,
std::function<void(int32_t, int32_t)>&& callback) override;
Rect GetBoundingRectData(NodeId nodeId) override;
std::string GetInspector(NodeId nodeId) override;
void PushJsCallbackToRenderNode(NodeId id, double ratio, std::function<void(bool, double)>&& callback) override;
void SetCallBackResult(const std::string& callBackId, const std::string& result) override;
void WaitTimer(const std::string& callbackId, const std::string& delay, bool isInterval, bool isFirst) override;
void ClearTimer(const std::string& callbackId) override;
void PostSyncTaskToPage(std::function<void()>&& task, const std::string& name) override;
void AddTaskObserver(std::function<void()>&& task) override;
void RemoveTaskObserver() override;
bool GetAssetContent(const std::string& url, std::string& content) override;
bool GetAssetContent(const std::string& url, std::vector<uint8_t>& content) override;
std::string GetAssetPath(const std::string& url) override;
void GetI18nData(std::unique_ptr<JsonValue>& json) override;
void GetResourceConfiguration(std::unique_ptr<JsonValue>& json) override;
void GetConfigurationCommon(const std::string& filePath, std::unique_ptr<JsonValue>& data) override;
void ChangeLocale(const std::string& language, const std::string& countryOrRegion) override;
void RegisterFont(const std::string& familyName, const std::string& familySrc, const std::string& bundleName = "",
const std::string& moduleName = "") override;
void GetSystemFontList(std::vector<std::string>& fontList) override;
bool GetSystemFont(const std::string& fontName, FontInfo& fontInfo) override;
void GetUIFontConfig(FontConfigJsonInfo& fontConfigJsonInfo) override;
void HandleImage(const std::string& src, std::function<void(bool, int32_t, int32_t)>&& callback) override;
void RequestAnimationFrame(const std::string& callbackId) override;
void CancelAnimationFrame(const std::string& callbackId) override;
void SetMonitorForCrownEvents(const std::string& callbackId) override;
void ClearMonitorForCrownEvents() override;
SingleTaskExecutor GetAnimationJsTask() override;
SingleTaskExecutor GetUiTask() override;
void LoadResourceConfiguration(std::map<std::string, std::string>& sortedResourcePath,
std::unique_ptr<JsonValue>& currentResourceData) override;
const RefPtr<MediaQueryInfo>& GetMediaQueryInfoInstance() override
{
return mediaQueryInfo_;
}
const RefPtr<GroupJsBridge>& GetGroupJsBridge() override
{
return groupJsBridge_;
}
RefPtr<PipelineBase> GetPipelineContext() override;
void SetGroupJsBridge(const RefPtr<GroupJsBridge>& groupJsBridge)
{
groupJsBridge_ = groupJsBridge;
}
RefPtr<JsAcePage> GetPage(int32_t pageId) const override;
WeakPtr<JsAcePage> GetCurrentReadyPage() const
{
return currentReadyPage_;
}
bool GetPagePathInvalidFlag() const
{
return isPagePathInvalid_;
}
void RebuildAllPages();
void CallNativeHandler(const std::string& event, const std::string& params) override;
private:
void Push(const std::string& uri, const std::string& params,
const std::function<void(const std::string&, int32_t)>& errorCallback);
void Replace(const std::string& uri, const std::string& params,
const std::function<void(const std::string&, int32_t)>& errorCallback);
int32_t GenerateNextPageId();
void RecyclePageId(int32_t pageId);
UIContentErrorCode LoadPage(int32_t pageId, const std::string& url, bool isMainPage, const std::string& params);
void OnPageReady(const RefPtr<Framework::JsAcePage>& page, const std::string& url, bool isMainPage);
void FlushPageCommand(const RefPtr<Framework::JsAcePage>& page, const std::string& url, bool isMainPage);
void AddPageLocked(const RefPtr<JsAcePage>& page);
void SetCurrentPage(int32_t pageId);
void SetCurrentReadyPage(const WeakPtr<JsAcePage>& page)
{
currentReadyPage_ = page;
}
void OnPushPageSuccess(const RefPtr<JsAcePage>& page, const std::string& url);
void OnPopToPageSuccess(const std::string& url);
void PopToPage(const std::string& url);
int32_t OnPopPageSuccess();
void PopPage();
void PushPageTransitionListener(const TransitionEvent& event, const RefPtr<JsAcePage>& page);
void PopPageTransitionListener(const TransitionEvent& event, int32_t destroyPageId);
void PopToPageTransitionListener(const TransitionEvent& event, const std::string& url, int32_t pageId);
int32_t OnClearInvisiblePagesSuccess();
void ClearInvisiblePages();
void OnReplacePageSuccess(const RefPtr<JsAcePage>& page, const std::string& url);
void ReplacePage(const RefPtr<JsAcePage>& page, const std::string& url);
void LoadReplacePage(int32_t pageId, const std::string& url, const std::string& params);
uint64_t GetSystemRealTime();
void OnPageShow();
void OnPageHide();
void OnPageDestroy(int32_t pageId);
int32_t GetRunningPageId() const;
std::string GetRunningPageUrl() const;
int32_t GetPageIdByUrl(const std::string& url);
void ResetStagingPage();
void FlushAnimationTasks();
void ParseManifest();
void BackImplement(const std::string& uri, const std::string& params);
void ClearAlertCallback(PageInfo pageInfo);
void GetAssetFromI18n(const std::string& fileFullPath, std::unique_ptr<JsonValue>& data);
bool OnMonitorForCrownEvents(const std::string& callbackId, const std::string& args);
std::atomic<uint64_t> pageIdPool_ = 0;
int32_t callbackCnt_ = 0;
int32_t pageId_ = -1;
bool isRouteStackFull_ = false;
bool isStagingPageExist_ = false;
std::string mainPagePath_;
std::string backUri_;
std::string backParam_;
std::vector<PageInfo> pageRouteStack_;
std::unordered_map<int32_t, RefPtr<JsAcePage>> pageMap_;
std::unordered_map<int32_t, std::string> pageParamMap_;
std::unordered_map<int32_t, std::string> jsCallBackResult_;
WeakPtr<JsAcePage> currentReadyPage_;
LoadJsCallback loadJs_;
JsMessageDispatcherSetterCallback dispatcherCallback_;
EventCallback asyncEvent_;
EventCallback syncEvent_;
ExternalEventCallback externalEvent_;
UpdatePageCallback updatePage_;
ResetStagingPageCallback resetStagingPage_;
DestroyPageCallback destroyPage_;
DestroyApplicationCallback destroyApplication_;
UpdateApplicationStateCallback updateApplicationState_;
OnStartContinuationCallBack onStartContinuationCallBack_;
OnCompleteContinuationCallBack onCompleteContinuationCallBack_;
OnRemoteTerminatedCallBack onRemoteTerminatedCallBack_;
OnSaveDataCallBack onSaveDataCallBack_;
OnRestoreDataCallBack onRestoreDataCallBack_;
TimerCallback timer_;
std::unordered_map<std::string, CancelableCallback<void()>> timeoutTaskMap_;
MediaQueryCallback mediaQueryCallback_;
RequestAnimationCallback requestAnimationCallback_;
JsCallback jsCallback_;
RefPtr<Framework::ManifestParser> manifestParser_;
RefPtr<Framework::AccessibilityNodeManager> jsAccessibilityManager_;
RefPtr<MediaQueryInfo> mediaQueryInfo_;
RefPtr<GroupJsBridge> groupJsBridge_;
RefPtr<TaskExecutor> taskExecutor_;
CallNativeHandlerCallback callNativeHandler_;
OnDigitalCrownCallback onCrownEventCallback_;
PipelineContextHolder pipelineContextHolder_;
BaseId::IdType pageTransitionListenerId_ = 0L;
std::queue<std::string> animationFrameTaskIds_;
std::unordered_map<std::string, CancelableCallback<void()>> animationFrameTaskMap_;
mutable std::mutex mutex_;
mutable std::once_flag onceFlag_;
bool isPagePathInvalid_ = false;
};
}
#endif