1/*
2 * Copyright (c) 2024 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 "arkweb_interface.h"
17
18#include "arkweb_type.h"
19#include "nweb_helper.h"
20#include "nweb_log.h"
21#include "arkweb_error_code.h"
22
23namespace {
24#define ARKWEB_NATIVE_FOR_EACH_COMPONENT_API_FN(DO)           \
25    DO(onControllerAttached, OH_ArkWeb_OnControllerAttached); \
26    DO(onPageBegin, OH_ArkWeb_OnPageBegin);                   \
27    DO(onPageEnd, OH_ArkWeb_OnPageEnd);                       \
28    DO(onDestroy, OH_ArkWeb_OnDestroy)
29
30#define ARKWEB_NATIVE_FOR_EACH_CONTROLLER_API_FN(DO)                          \
31    DO(runJavaScript, OH_ArkWeb_RunJavaScript);                               \
32    DO(registerJavaScriptProxy, OH_ArkWeb_RegisterJavaScriptProxy);           \
33    DO(deleteJavaScriptRegister, OH_ArkWeb_DeleteJavaScriptProxy);            \
34    DO(refresh, OH_ArkWeb_Refresh);                                           \
35    DO(registerAsyncJavaScriptProxy, OH_ArkWeb_RegisterAsyncJavaScriptProxy); \
36    DO(createWebMessagePorts, OH_ArkWeb_CreateWebMessagePorts);               \
37    DO(destroyWebMessagePorts, OH_ArkWeb_DestroyWebMessagePorts);             \
38    DO(postWebMessage, OH_ArkWeb_PostWebMessage)
39
40#define ARKWEB_NATIVE_FOR_EACH_WEBMESSAGEPORT_API_FN(DO) \
41    DO(postMessage, OH_WebMessage_PostMessage);          \
42    DO(close, OH_WebMessage_Close);                      \
43    DO(setMessageEventHandler, OH_WebMessage_SetMessageEventHandler)
44
45#define ARKWEB_NATIVE_FOR_EACH_WEBMESSAGE_API_FN(DO)        \
46    DO(createWebMessage, OH_WebMessage_CreateWebMessage);   \
47    DO(destroyWebMessage, OH_WebMessage_DestroyWebMessage); \
48    DO(setType, OH_WebMessage_SetType);                     \
49    DO(getType, OH_WebMessage_GetType);                     \
50    DO(setData, OH_WebMessage_SetData);                     \
51    DO(getData, OH_WebMessage_GetData)
52
53#define ARKWEB_NATIVE_FOR_EACH_WEBCOOKIEMANAGER_API_FN(DO)                \
54    DO(fetchCookieSync, OH_CookieManager_FetchCookieSync);                \
55    DO(configCookieSync, OH_CookieManager_ConfigCookieSync);              \
56    DO(existCookies, OH_CookieManager_ExistCookies);                      \
57    DO(clearAllCookiesSync, OH_CookieManager_ClearAllCookiesSync);        \
58    DO(clearSessionCookiesSync, OH_CookieManager_ClearSessionCookiesSync)
59
60ArkWeb_ComponentAPI* g_ComponentImpl = nullptr;
61ArkWeb_ControllerAPI* g_ControllerImpl = nullptr;
62ArkWeb_WebMessagePortAPI* g_WebMessagePortImpl = nullptr;
63ArkWeb_WebMessageAPI* g_WebMessageImpl = nullptr;
64ArkWeb_CookieManagerAPI* g_CookieManagerImpl = nullptr;
65
66} // namespace
67
68template<typename Fn>
69static void LoadFunction(const char* functionName, Fn* fnOut)
70{
71    void* fn = OHOS::NWeb::NWebHelper::Instance().LoadFuncSymbol(functionName);
72    if (!fn) {
73        WVLOG_E("%{public}s not found.", functionName);
74        return;
75    }
76    *fnOut = reinterpret_cast<Fn>(fn);
77}
78
79static bool LoadComponentAPI()
80{
81    if (g_ComponentImpl) {
82        WVLOG_I("NativeArkWeb component api already loaded");
83        return true;
84    }
85    g_ComponentImpl = new (std::nothrow) ArkWeb_ComponentAPI();
86    if (!g_ComponentImpl) {
87        WVLOG_E("NativeArkWeb component api is nullptr");
88        return false;
89    }
90    g_ComponentImpl->size = sizeof(ArkWeb_ComponentAPI);
91
92    if (!OHOS::NWeb::NWebHelper::Instance().LoadWebEngine(true, false)) {
93        WVLOG_E("NativeArkWeb webEngineHandle is nullptr");
94        return false;
95    }
96#define ARKWEB_NATIVE_LOAD_FN_PTR(fn, ndkFn) LoadFunction(#ndkFn, &(g_ComponentImpl->fn))
97    ARKWEB_NATIVE_FOR_EACH_COMPONENT_API_FN(ARKWEB_NATIVE_LOAD_FN_PTR);
98#undef ARKWEB_NATIVE_LOAD_FN_PTR
99
100    return true;
101}
102
103static bool LoadControllerAPI()
104{
105    if (g_ControllerImpl) {
106        WVLOG_I("NativeArkWeb controller api already loaded");
107        return true;
108    }
109    g_ControllerImpl = new (std::nothrow) ArkWeb_ControllerAPI();
110    if (!g_ControllerImpl) {
111        WVLOG_E("NativeArkWeb controller api is nullptr");
112        return false;
113    }
114    g_ControllerImpl->size = sizeof(ArkWeb_ControllerAPI);
115
116    if (!OHOS::NWeb::NWebHelper::Instance().LoadWebEngine(true, false)) {
117        WVLOG_E("NativeArkWeb webEngineHandle is nullptr");
118        return false;
119    }
120#define ARKWEB_NATIVE_LOAD_FN_PTR(fn, ndkFn) LoadFunction(#ndkFn, &(g_ControllerImpl->fn))
121    ARKWEB_NATIVE_FOR_EACH_CONTROLLER_API_FN(ARKWEB_NATIVE_LOAD_FN_PTR);
122#undef ARKWEB_NATIVE_LOAD_FN_PTR
123
124    return true;
125}
126
127static bool LoadWebMessagePortAPI()
128{
129    if (g_WebMessagePortImpl) {
130        WVLOG_I("NativeArkWeb web message port api already loaded");
131        return true;
132    }
133    g_WebMessagePortImpl = new (std::nothrow) ArkWeb_WebMessagePortAPI();
134    if (!g_WebMessagePortImpl) {
135        WVLOG_E("NativeArkWeb web message port api is nullptr");
136        return false;
137    }
138    g_WebMessagePortImpl->size = sizeof(ArkWeb_WebMessagePortAPI);
139
140    if (!OHOS::NWeb::NWebHelper::Instance().LoadWebEngine(true, false)) {
141        WVLOG_E("NativeArkWeb webEngineHandle is nullptr");
142        return false;
143    }
144#define ARKWEB_NATIVE_LOAD_FN_PTR(fn, ndkFn) LoadFunction(#ndkFn, &(g_WebMessagePortImpl->fn))
145    ARKWEB_NATIVE_FOR_EACH_WEBMESSAGEPORT_API_FN(ARKWEB_NATIVE_LOAD_FN_PTR);
146#undef ARKWEB_NATIVE_LOAD_FN_PTR
147
148    return true;
149}
150
151static bool LoadWebMessageAPI()
152{
153    if (g_WebMessageImpl) {
154        WVLOG_I("NativeArkWeb web message api already loaded");
155        return true;
156    }
157    g_WebMessageImpl = new (std::nothrow) ArkWeb_WebMessageAPI();
158    if (!g_WebMessageImpl) {
159        WVLOG_E("NativeArkWeb web message api is nullptr");
160        return false;
161    }
162    g_WebMessageImpl->size = sizeof(ArkWeb_WebMessageAPI);
163
164    if (!OHOS::NWeb::NWebHelper::Instance().LoadWebEngine(true, false)) {
165        WVLOG_E("NativeArkWeb webEngineHandle is nullptr");
166        return false;
167    }
168#define ARKWEB_NATIVE_LOAD_FN_PTR(fn, ndkFn) LoadFunction(#ndkFn, &(g_WebMessageImpl->fn))
169    ARKWEB_NATIVE_FOR_EACH_WEBMESSAGE_API_FN(ARKWEB_NATIVE_LOAD_FN_PTR);
170#undef ARKWEB_NATIVE_LOAD_FN_PTR
171
172    return true;
173}
174
175static bool LoadCookieManagerAPI()
176{
177    if (g_CookieManagerImpl) {
178        WVLOG_I("NativeArkWeb cookie manager api already loaded");
179        return true;
180    }
181
182    g_CookieManagerImpl = new ArkWeb_CookieManagerAPI();
183    if (!g_CookieManagerImpl) {
184        WVLOG_E("NativeArkWeb cookie manager api is nullptr");
185        return false;
186    }
187    g_CookieManagerImpl->size = sizeof(ArkWeb_CookieManagerAPI);
188
189    if (!OHOS::NWeb::NWebHelper::Instance().LoadWebEngine(true, true)) {
190        WVLOG_E("NativeArkWeb webEngineHandle is nullptr");
191        return false;
192    }
193#define ARKWEB_NATIVE_LOAD_FN_PTR(fn, ndkFn) LoadFunction(#ndkFn, &(g_CookieManagerImpl->fn))
194    ARKWEB_NATIVE_FOR_EACH_WEBCOOKIEMANAGER_API_FN(ARKWEB_NATIVE_LOAD_FN_PTR);
195#undef ARKWEB_NATIVE_LOAD_FN_PTR
196
197    return true;
198}
199
200ArkWeb_AnyNativeAPI* OH_ArkWeb_GetNativeAPI(ArkWeb_NativeAPIVariantKind type)
201{
202    switch (type) {
203        case ARKWEB_NATIVE_COMPONENT: {
204            if (!LoadComponentAPI()) {
205                return nullptr;
206            }
207            return reinterpret_cast<ArkWeb_AnyNativeAPI*>(g_ComponentImpl);
208        }
209        case ARKWEB_NATIVE_CONTROLLER: {
210            if (!LoadControllerAPI()) {
211                return nullptr;
212            }
213            return reinterpret_cast<ArkWeb_AnyNativeAPI*>(g_ControllerImpl);
214        }
215        case ARKWEB_NATIVE_WEB_MESSAGE_PORT: {
216            if (!LoadWebMessagePortAPI()) {
217                return nullptr;
218            }
219            return reinterpret_cast<ArkWeb_AnyNativeAPI*>(g_WebMessagePortImpl);
220        }
221        case ARKWEB_NATIVE_WEB_MESSAGE: {
222            if (!LoadWebMessageAPI()) {
223                return nullptr;
224            }
225            return reinterpret_cast<ArkWeb_AnyNativeAPI*>(g_WebMessageImpl);
226        }
227        case ARKWEB_NATIVE_COOKIE_MANAGER: {
228            if (!LoadCookieManagerAPI()) {
229                return nullptr;
230            }
231            return reinterpret_cast<ArkWeb_AnyNativeAPI*>(g_CookieManagerImpl);
232        }
233        default: {
234            WVLOG_E("fail to get %{public}d arkweb api family", type);
235            return nullptr;
236        }
237    }
238}
239