1/*
2 * Copyright (c) 2023 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 "native_interface_arkweb.h"
17
18#include <memory>
19#include <mutex>
20#include <unordered_map>
21#include <vector>
22
23#include "native_arkweb_utils.h"
24#include "native_javascript_execute_callback.h"
25#include "nweb.h"
26#include "nweb_log.h"
27
28namespace {
29std::mutex g_mtxMap; // the mutex to protect the shared resource
30std::unordered_map<std::string, NativeArkWeb_OnValidCallback> g_validMap;
31std::unordered_map<std::string, NativeArkWeb_OnDestroyCallback> g_destroyMap;
32} // namespace
33
34namespace OHOS::NWeb {
35
36class NWebJsProxyCallbackImpl : public NWebJsProxyCallback {
37public:
38    NWebJsProxyCallbackImpl(const char *methodName, NativeArkWeb_OnJavaScriptProxyCallback methodCallback)
39        : methodName_(methodName), methodCallback_(methodCallback) {
40    }
41    ~NWebJsProxyCallbackImpl() = default;
42
43    std::string GetMethodName() override
44    {
45        return methodName_;
46    }
47
48    NativeArkWeb_OnJavaScriptProxyCallback GetMethodCallback() override
49    {
50        return methodCallback_;
51    }
52
53private:
54    std::string methodName_;
55    NativeArkWeb_OnJavaScriptProxyCallback methodCallback_ = nullptr;
56};
57
58}; // namespace OHOS::NWeb
59
60using namespace OHOS;
61void OH_NativeArkWeb_RunJavaScript(const char* webTag, const char* jsCode, NativeArkWeb_OnJavaScriptCallback callback)
62{
63    std::weak_ptr<OHOS::NWeb::NWeb> nwebWeak = OH_NativeArkWeb_GetWebInstanceByWebTag(webTag);
64    if (auto nweb = nwebWeak.lock()) {
65        auto callbackImpl = std::make_shared<OHOS::NWeb::NativeJavaScriptExecuteCallback>(callback);
66        WVLOG_I("native RunJavaScript webTag: %{public}s", webTag);
67        nweb->ExecuteJavaScript(jsCode, callbackImpl, false);
68    } else {
69        WVLOG_E("native RunJavaScript get nweb null: %{public}s", webTag);
70    }
71}
72
73void OH_NativeArkWeb_RegisterJavaScriptProxy(const char* webTag, const char* objName, const char** methodList,
74    NativeArkWeb_OnJavaScriptProxyCallback* callback, int32_t size, bool isNeedRefresh)
75{
76    WVLOG_I("native OH_NativeArkWeb_RegisterJavaScriptProxy webTag:%{public}s", webTag);
77    std::vector<std::shared_ptr<OHOS::NWeb::NWebJsProxyCallback>> proxyCallbacks;
78    for (int i = 0; i < size; i++) {
79        std::shared_ptr<OHOS::NWeb::NWebJsProxyCallback> proxyCallback =
80            std::make_shared<OHOS::NWeb::NWebJsProxyCallbackImpl>(methodList[i], callback[i]);
81        proxyCallbacks.push_back(proxyCallback);
82    }
83
84    std::weak_ptr<OHOS::NWeb::NWeb> nwebWeak = OH_NativeArkWeb_GetWebInstanceByWebTag(webTag);
85    if (auto nweb = nwebWeak.lock()) {
86        nweb->RegisterNativeArkJSFunction(objName, proxyCallbacks);
87        if (isNeedRefresh) {
88            nweb->Reload();
89        }
90    } else {
91        WVLOG_E("native RegisterJavaScriptProxy get nweb null: %{public}s", webTag);
92    }
93}
94
95void OH_NativeArkWeb_UnregisterJavaScriptProxy(const char* webTag, const char* objName)
96{
97    WVLOG_I("native OH_NativeArkWeb_RegisterJavaScriptProxy: %{public}s", webTag);
98    std::weak_ptr<OHOS::NWeb::NWeb> nwebWeak = OH_NativeArkWeb_GetWebInstanceByWebTag(webTag);
99    if (auto nweb = nwebWeak.lock()) {
100        nweb->UnRegisterNativeArkJSFunction(objName);
101    } else {
102        WVLOG_E("native RegisterJavaScriptProxy get nweb null: %{public}s", webTag);
103    }
104}
105
106void OH_NativeArkWeb_SetDestroyCallback(const char* webTag, NativeArkWeb_OnDestroyCallback callback)
107{
108    WVLOG_I("native RegisterDestroyCallback, webTag: %{public}s", webTag);
109    std::lock_guard<std::mutex> guard(g_mtxMap);
110    g_destroyMap[webTag] = callback;
111    std::weak_ptr<OHOS::NWeb::NWeb> nwebWeak = OH_NativeArkWeb_GetWebInstanceByWebTag(webTag);
112    if (auto nweb = nwebWeak.lock()) {
113        WVLOG_I("native RegisterNativeDestroyCallback call nweb");
114        nweb->RegisterNativeDestroyCallback(webTag, callback);
115    } else {
116        WVLOG_E("native RegisterDestroyCallback get nweb null: %{public}s", webTag);
117    }
118}
119
120NativeArkWeb_OnDestroyCallback OH_NativeArkWeb_GetDestroyCallback(const char* webTag)
121{
122    WVLOG_I("native OH_Web_GetDestroyCallback, webTag: %{public}s", webTag);
123    std::lock_guard<std::mutex> guard(g_mtxMap);
124    std::unordered_map<std::string, NativeArkWeb_OnDestroyCallback>::iterator iter;
125    if ((iter = g_destroyMap.find(webTag)) != g_destroyMap.end()) {
126        return iter->second;
127    }
128    return nullptr;
129}
130
131void OH_NativeArkWeb_SetJavaScriptProxyValidCallback(const char* webTag, NativeArkWeb_OnValidCallback callback)
132{
133    WVLOG_I("native RegisterValidCallback, webTag: %{public}s", webTag);
134    std::lock_guard<std::mutex> guard(g_mtxMap);
135    g_validMap[webTag] = callback;
136    std::weak_ptr<OHOS::NWeb::NWeb> nwebWeak = OH_NativeArkWeb_GetWebInstanceByWebTag(webTag);
137    if (auto nweb = nwebWeak.lock()) {
138        WVLOG_I("native OH_NativeArkWeb_SetJavaScriptProxyValidCallback call nweb");
139        nweb->RegisterNativeValideCallback(webTag, callback);
140    } else {
141        WVLOG_E("native RegisterDestroyCallback get nweb null: %{public}s", webTag);
142    }
143}
144
145NativeArkWeb_OnValidCallback OH_NativeArkWeb_GetJavaScriptProxyValidCallback(const char* webTag)
146{
147    WVLOG_I("native OH_Web_GetValidCallback, webTag: %{public}s", webTag);
148    std::lock_guard<std::mutex> guard(g_mtxMap);
149    std::unordered_map<std::string, NativeArkWeb_OnValidCallback>::iterator iter;
150    if ((iter = g_validMap.find(webTag)) != g_validMap.end()) {
151        return iter->second;
152    }
153    return nullptr;
154}
155