no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View File

@@ -0,0 +1,208 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "WebView.h"
#include "base/memory/Memory.h"
#include "platform/FileUtils.h"
#if CC_PLATFORM == CC_PLATFORM_IOS
#include "WebViewImpl-ios.h"
#elif CC_PLATFORM == CC_PLATFORM_ANDROID || CC_PLATFORM == CC_PLATFORM_OHOS || CC_PLATFORM == CC_PLATFORM_OPENHARMONY
#include "WebViewImpl-java.h"
#else
static_assert(false, "WebView only supported on iOS & Android");
#endif
namespace cc {
WebView::WebView()
: _impl(ccnew WebViewImpl(this)),
_onJSCallback(nullptr),
_onShouldStartLoading(nullptr),
_onDidFinishLoading(nullptr),
_onDidFailLoading(nullptr) {
}
WebView::~WebView() {
CC_SAFE_DELETE(_impl);
}
WebView *WebView::create() {
auto webView = ccnew WebView();
if (webView) {
return webView;
}
return nullptr;
}
void WebView::destroy() {
CC_SAFE_DESTROY(_impl);
}
void WebView::setJavascriptInterfaceScheme(const ccstd::string &scheme) {
if (_impl != nullptr) {
_impl->setJavascriptInterfaceScheme(scheme);
}
}
void WebView::loadData(const cc::Data &data,
const ccstd::string &MIMEType,
const ccstd::string &encoding,
const ccstd::string &baseURL) {
if (_impl != nullptr) {
_impl->loadData(data, MIMEType, encoding, baseURL);
}
}
void WebView::loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL) {
if (_impl != nullptr) {
_impl->loadHTMLString(string, baseURL);
}
}
void WebView::loadURL(const ccstd::string &url) {
if (_impl != nullptr) {
_impl->loadURL(url);
}
}
void WebView::loadFile(const ccstd::string &fileName) {
if (_impl != nullptr) {
_impl->loadFile(fileName);
}
}
void WebView::stopLoading() {
if (_impl != nullptr) {
_impl->stopLoading();
}
}
void WebView::reload() {
if (_impl != nullptr) {
_impl->reload();
}
}
bool WebView::canGoBack() {
if (_impl != nullptr) {
return _impl->canGoBack();
}
return false;
}
bool WebView::canGoForward() {
if (_impl != nullptr) {
return _impl->canGoForward();
}
return false;
}
void WebView::goBack() {
if (_impl != nullptr) {
_impl->goBack();
}
}
void WebView::goForward() {
if (_impl != nullptr) {
_impl->goForward();
}
}
void WebView::evaluateJS(const ccstd::string &js) {
if (_impl != nullptr) {
_impl->evaluateJS(js);
}
}
void WebView::setScalesPageToFit(bool scalesPageToFit) {
if (_impl != nullptr) {
_impl->setScalesPageToFit(scalesPageToFit);
}
}
void WebView::setVisible(bool visible) {
if (_impl != nullptr) {
_impl->setVisible(visible);
}
}
void WebView::setFrame(float x, float y, float width, float height) {
if (_impl != nullptr) {
_impl->setFrame(x, y, width, height);
}
}
void WebView::setBounces(bool bounces) {
if (_impl != nullptr) {
_impl->setBounces(bounces);
}
}
void WebView::setBackgroundTransparent(bool isTransparent) {
if (_impl != nullptr) {
_impl->setBackgroundTransparent(isTransparent);
}
}
void WebView::setOnDidFailLoading(const ccWebViewCallback &callback) {
_onDidFailLoading = callback;
}
void WebView::setOnDidFinishLoading(const ccWebViewCallback &callback) {
_onDidFinishLoading = callback;
}
void WebView::setOnShouldStartLoading(
const std::function<bool(WebView *sender, const ccstd::string &url)> &callback) {
_onShouldStartLoading = callback;
}
void WebView::setOnJSCallback(const ccWebViewCallback &callback) {
_onJSCallback = callback;
}
std::function<bool(WebView
*sender,
const ccstd::string &url)>
WebView::getOnShouldStartLoading() const {
return _onShouldStartLoading;
}
WebView::ccWebViewCallback WebView::getOnDidFailLoading() const {
return _onDidFailLoading;
}
WebView::ccWebViewCallback WebView::getOnDidFinishLoading() const {
return _onDidFinishLoading;
}
WebView::ccWebViewCallback WebView::getOnJSCallback() const {
return _onJSCallback;
}
} //namespace cc

247
cocos/ui/webview/WebView.h Normal file
View File

@@ -0,0 +1,247 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <functional>
#include "base/Data.h"
#include "base/Macros.h"
#include "base/RefCounted.h"
#include "base/std/container/string.h"
/**
* @addtogroup ui
* @{
*/
namespace cc {
class WebViewImpl;
/**
* @brief A View that displays web pages.
*
* @note WebView displays web pages base on system widget.
* It's mean WebView displays web pages above all graphical elements of cocos2d-x.
* @js NA
*/
class WebView final {
public:
/**
* Allocates and initializes a WebView.
*/
static WebView *create();
/**
* Destroy webview, remove it from its parent
*/
void destroy();
/**
* Set javascript interface scheme.
*
* @see WebView::setOnJSCallback()
*/
void setJavascriptInterfaceScheme(const ccstd::string &scheme);
/**
* Sets the main page contents, MIME type, content encoding, and base URL.
*
* @param data The content for the main page.
* @param mimeType The MIME type of the data.
* @param encoding The encoding of the data.
* @param baseURL The base URL for the content.
*/
void loadData(const cc::Data &data,
const ccstd::string &mimeType,
const ccstd::string &encoding,
const ccstd::string &baseURL);
/**
* Sets the main page content and base URL.
*
* @param string The content for the main page.
* @param baseURL The base URL for the content.
*/
void loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL = "");
/**
* Loads the given URL.
*
* @param url Content URL.
*/
void loadURL(const ccstd::string &url);
/**
* Loads the given fileName.
*
* @param fileName Content fileName.
*/
void loadFile(const ccstd::string &fileName);
/**
* Stops the current load.
*/
void stopLoading();
/**
* Reloads the current URL.
*/
void reload();
/**
* Gets whether this WebView has a back history item.
*
* @return WebView has a back history item.
*/
bool canGoBack();
/**
* Gets whether this WebView has a forward history item.
*
* @return WebView has a forward history item.
*/
bool canGoForward();
/**
* Goes back in the history.
*/
void goBack();
/**
* Goes forward in the history.
*/
void goForward();
/**
* Evaluates JavaScript in the context of the currently displayed page.
*/
void evaluateJS(const ccstd::string &js);
/**
* Set WebView should support zooming. The default value is false.
*/
void setScalesPageToFit(bool scalesPageToFit);
/**
* Call before a web view begins loading.
*
* @param callback The web view that is about to load new content.
* @return YES if the web view should begin loading content; otherwise, NO.
*/
void setOnShouldStartLoading(
const std::function<bool(WebView *sender, const ccstd::string &url)> &callback);
/**
* A callback which will be called when a WebView event happens.
*/
using ccWebViewCallback = std::function<void(WebView *, const ccstd::string &)>;
/**
* Call after a web view finishes loading.
*
* @param callback The web view that has finished loading.
*/
void setOnDidFinishLoading(const ccWebViewCallback &callback);
/**
* Call if a web view failed to load content.
*
* @param callback The web view that has failed loading.
*/
void setOnDidFailLoading(const ccWebViewCallback &callback);
/**
* This callback called when load URL that start with javascript interface scheme.
*/
void setOnJSCallback(const ccWebViewCallback &callback);
/**
* Get the callback when WebView is about to start.
*/
std::function<bool(WebView *sender, const ccstd::string &url)>
getOnShouldStartLoading() const;
/**
* Get the callback when WebView has finished loading.
*/
ccWebViewCallback getOnDidFinishLoading() const;
/**
* Get the callback when WebView has failed loading.
*/
ccWebViewCallback getOnDidFailLoading() const;
/**
*Get the Javascript callback.
*/
ccWebViewCallback getOnJSCallback() const;
/**
* Set whether the webview bounces at end of scroll of WebView.
*/
void setBounces(bool bounce);
/**
* Toggle visibility of WebView.
*/
virtual void setVisible(bool visible);
/**
* Set the rect of WebView.
*/
virtual void setFrame(float x, float y, float width, float height);
/**
* Set the background transparent
*/
virtual void setBackgroundTransparent(bool isTransparent);
protected:
std::function<bool(WebView *sender, const ccstd::string &url)> _onShouldStartLoading;
ccWebViewCallback _onDidFinishLoading;
ccWebViewCallback _onDidFailLoading;
ccWebViewCallback _onJSCallback;
/**
* Default constructor.
*/
WebView();
/**
* Default destructor.
*/
~WebView();
private:
WebViewImpl *_impl;
friend class WebViewImpl;
};
} // namespace cc

View File

@@ -0,0 +1,300 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <cstdlib>
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
#include "WebView-inl.h"
#include "platform/FileUtils.h"
#include "platform/java/jni/JniHelper.h"
static const ccstd::string CLASS_NAME = "com/cocos/lib/CocosWebViewHelper";
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "", __VA_ARGS__)
static const ccstd::string S_DEFAULT_BASE_URL = "file:///android_asset/";
static const ccstd::string S_SD_ROOT_BASE_URL = "file://";
static ccstd::string getFixedBaseUrl(const ccstd::string &baseUrl) {
ccstd::string fixedBaseUrl;
if (baseUrl.empty()) {
fixedBaseUrl = S_DEFAULT_BASE_URL;
} else if (baseUrl.find(S_SD_ROOT_BASE_URL) != ccstd::string::npos) {
fixedBaseUrl = baseUrl;
} else if (baseUrl.c_str()[0] != '/') {
if (baseUrl.find("assets/") == 0) {
fixedBaseUrl = S_DEFAULT_BASE_URL + baseUrl.c_str()[7];
} else {
fixedBaseUrl = S_DEFAULT_BASE_URL + baseUrl;
}
} else {
fixedBaseUrl = S_SD_ROOT_BASE_URL + baseUrl;
}
if (fixedBaseUrl.c_str()[fixedBaseUrl.length() - 1] != '/') {
fixedBaseUrl += "/";
}
return fixedBaseUrl;
}
extern "C" {
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: shouldStartLoading
* Signature: (ILjava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL
Java_com_cocos_lib_CocosWebViewHelper_shouldStartLoading(JNIEnv *env, jclass, jint index, //NOLINT
jstring jurl) {
const auto *charUrl = env->GetStringUTFChars(jurl, nullptr);
ccstd::string url = charUrl;
env->ReleaseStringUTFChars(jurl, charUrl);
return cc::WebViewImpl::shouldStartLoading(index, url);
}
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: didFinishLoading
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_com_cocos_lib_CocosWebViewHelper_didFinishLoading(JNIEnv *env, jclass, jint index, //NOLINT
jstring jurl) {
// LOGD("didFinishLoading");
const auto *charUrl = env->GetStringUTFChars(jurl, nullptr);
ccstd::string url = charUrl;
env->ReleaseStringUTFChars(jurl, charUrl);
cc::WebViewImpl::didFinishLoading(index, url);
}
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: didFailLoading
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_com_cocos_lib_CocosWebViewHelper_didFailLoading(JNIEnv *env, jclass, jint index, //NOLINT
jstring jurl) {
// LOGD("didFailLoading");
const auto *charUrl = env->GetStringUTFChars(jurl, nullptr);
ccstd::string url = charUrl;
env->ReleaseStringUTFChars(jurl, charUrl);
cc::WebViewImpl::didFailLoading(index, url);
}
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: onJsCallback
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_com_cocos_lib_CocosWebViewHelper_onJsCallback(JNIEnv *env, jclass, jint index, //NOLINT
jstring jmessage) {
// LOGD("jsCallback");
const auto *charMessage = env->GetStringUTFChars(jmessage, nullptr);
ccstd::string message = charMessage;
env->ReleaseStringUTFChars(jmessage, charMessage);
cc::WebViewImpl::onJsCallback(index, message);
}
}
namespace {
int createWebViewJNI() {
cc::JniMethodInfo t;
if (cc::JniHelper::getStaticMethodInfo(t, CLASS_NAME.c_str(), "createWebView", "()I")) {
// LOGD("error: %s,%d",__func__,__LINE__);
jint viewTag = t.env->CallStaticIntMethod(t.classID, t.methodID);
ccDeleteLocalRef(t.env, t.classID);
return viewTag;
}
return -1;
}
ccstd::string getUrlStringByFileName(const ccstd::string &fileName) {
// LOGD("error: %s,%d",__func__,__LINE__);
const ccstd::string basePath("file:///android_asset/");
ccstd::string fullPath = cc::FileUtils::getInstance()->fullPathForFilename(fileName);
const ccstd::string assetsPath("assets/");
ccstd::string urlString;
if (fullPath.find(assetsPath) != ccstd::string::npos) {
urlString = fullPath.replace(fullPath.find_first_of(assetsPath), assetsPath.length(),
basePath);
} else {
urlString = fullPath;
}
return urlString;
}
} // namespace
namespace cc {
static ccstd::unordered_map<int, WebViewImpl *> sWebViewImpls;
WebViewImpl::WebViewImpl(WebView *webView) : _viewTag(-1),
_webView(webView) {
_viewTag = createWebViewJNI();
sWebViewImpls[_viewTag] = this;
}
WebViewImpl::~WebViewImpl() {
destroy();
}
void WebViewImpl::destroy() {
if (_viewTag != -1) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "removeWebView", _viewTag);
auto iter = sWebViewImpls.find(_viewTag);
if (iter != sWebViewImpls.end()) {
sWebViewImpls.erase(iter);
}
_viewTag = -1;
}
}
void WebViewImpl::loadData(const Data &data, const ccstd::string &mimeType, // NOLINT
const ccstd::string &encoding, const ccstd::string &baseURL) { // NOLINT
ccstd::string dataString(reinterpret_cast<char *>(data.getBytes()),
static_cast<unsigned int>(data.getSize()));
JniHelper::callStaticVoidMethod(CLASS_NAME, "setJavascriptInterfaceScheme", _viewTag,
dataString, mimeType, encoding, baseURL);
}
void WebViewImpl::loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "loadHTMLString", _viewTag, string, baseURL);
}
void WebViewImpl::loadURL(const ccstd::string &url) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "loadUrl", _viewTag, url);
}
void WebViewImpl::loadFile(const ccstd::string &fileName) { // NOLINT
auto fullPath = getUrlStringByFileName(fileName);
JniHelper::callStaticVoidMethod(CLASS_NAME, "loadFile", _viewTag, fullPath);
}
void WebViewImpl::stopLoading() { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "stopLoading", _viewTag);
}
void WebViewImpl::reload() { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "reload", _viewTag);
}
bool WebViewImpl::canGoBack() { // NOLINT
return JniHelper::callStaticBooleanMethod(CLASS_NAME, "canGoBack", _viewTag);
}
bool WebViewImpl::canGoForward() { // NOLINT
return JniHelper::callStaticBooleanMethod(CLASS_NAME, "canGoForward", _viewTag);
}
void WebViewImpl::goBack() { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "goBack", _viewTag);
}
void WebViewImpl::goForward() { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "goForward", _viewTag);
}
void WebViewImpl::setJavascriptInterfaceScheme(const ccstd::string &scheme) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "setJavascriptInterfaceScheme", _viewTag,
scheme);
}
void WebViewImpl::evaluateJS(const ccstd::string &js) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "evaluateJS", _viewTag, js);
}
void WebViewImpl::setScalesPageToFit(bool scalesPageToFit) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "setScalesPageToFit", _viewTag, scalesPageToFit);
}
bool WebViewImpl::shouldStartLoading(int viewTag, const ccstd::string &url) {
bool allowLoad = true;
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto *webView = it->second->_webView;
if (webView->_onShouldStartLoading) {
allowLoad = webView->_onShouldStartLoading(webView, url);
}
}
return allowLoad;
}
void WebViewImpl::didFinishLoading(int viewTag, const ccstd::string &url) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto *webView = it->second->_webView;
if (webView->_onDidFinishLoading) {
webView->_onDidFinishLoading(webView, url);
}
}
}
void WebViewImpl::didFailLoading(int viewTag, const ccstd::string &url) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto *webView = it->second->_webView;
if (webView->_onDidFailLoading) {
webView->_onDidFailLoading(webView, url);
}
}
}
void WebViewImpl::onJsCallback(int viewTag, const ccstd::string &message) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto *webView = it->second->_webView;
if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message);
}
}
}
void WebViewImpl::setVisible(bool visible) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "setVisible", _viewTag, visible);
}
void WebViewImpl::setFrame(float x, float y, float width, float height) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "setWebViewRect", _viewTag,
static_cast<int>(x), static_cast<int>(y), static_cast<int>(width), static_cast<int>(height));
}
void WebViewImpl::setBounces(bool bounces) {
// empty function as this was mainly a fix for iOS
}
void WebViewImpl::setBackgroundTransparent(bool isTransparent) { // NOLINT
JniHelper::callStaticVoidMethod(CLASS_NAME, "setBackgroundTransparent", _viewTag,
isTransparent);
}
} //namespace cc

View File

@@ -0,0 +1,92 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __COCOS2D_UI_WEBVIEWIMPL_IOS_H_
#define __COCOS2D_UI_WEBVIEWIMPL_IOS_H_
/// @cond DO_NOT_SHOW
#include <iosfwd>
@class UIWebViewWrapper;
namespace cc {
class Data;
class WebView;
class WebViewImpl final {
public:
explicit WebViewImpl(WebView *webView);
~WebViewImpl();
void destroy();
void setJavascriptInterfaceScheme(const ccstd::string &scheme);
void loadData(const cc::Data &data,
const ccstd::string &MIMEType,
const ccstd::string &encoding,
const ccstd::string &baseURL);
void loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL);
void loadURL(const ccstd::string &url);
void loadFile(const ccstd::string &fileName);
void stopLoading();
void reload();
bool canGoBack();
bool canGoForward();
void goBack();
void goForward();
void evaluateJS(const ccstd::string &js);
void setScalesPageToFit(const bool scalesPageToFit);
void setVisible(bool visible);
void setFrame(float x, float y, float width, float height);
void setBounces(bool bounces);
void setBackgroundTransparent(bool isTransparent);
private:
UIWebViewWrapper *_uiWebViewWrapper;
WebView *_webView;
};
} //namespace cc
/// @endcond
#endif /* __COCOS2D_UI_WEBVIEWIMPL_IOS_H_ */

View File

@@ -0,0 +1,474 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2022 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#import <WebKit/WKWebView.h>
#import <WebKit/WKUIDelegate.h>
#import <WebKit/WKNavigationDelegate.h>
#include "WebView-inl.h"
#include "platform/FileUtils.h"
#include "platform/ios/WarpCocosContent.h"
@interface UIWebViewWrapper : NSObject
@property (nonatomic) std::function<bool(ccstd::string url)> shouldStartLoading;
@property (nonatomic) std::function<void(ccstd::string url)> didFinishLoading;
@property (nonatomic) std::function<void(ccstd::string url)> didFailLoading;
@property (nonatomic) std::function<void(ccstd::string url)> onJsCallback;
@property (nonatomic, readonly, getter=canGoBack) BOOL canGoBack;
@property (nonatomic, readonly, getter=canGoForward) BOOL canGoForward;
+ (instancetype)webViewWrapper;
- (void)setVisible:(bool)visible;
- (void)setBounces:(bool)bounces;
- (void)setFrame:(float)x y:(float)y width:(float)width height:(float)height;
- (void)setJavascriptInterfaceScheme:(const ccstd::string &)scheme;
- (void)loadData:(const ccstd::string &)data MIMEType:(const ccstd::string &)MIMEType textEncodingName:(const ccstd::string &)encodingName baseURL:(const ccstd::string &)baseURL;
- (void)loadHTMLString:(const ccstd::string &)string baseURL:(const ccstd::string &)baseURL;
- (void)loadUrl:(const ccstd::string &)urlString;
- (void)loadFile:(const ccstd::string &)filePath;
- (void)stopLoading;
- (void)reload;
- (void)evaluateJS:(const ccstd::string &)js;
- (void)goBack;
- (void)goForward;
- (void)setScalesPageToFit:(const bool)scalesPageToFit;
- (void)setBackgroundTransparent:(const bool)isTransparent;
@end
@interface UIWebViewWrapper () <WKUIDelegate, WKNavigationDelegate>
@property (nonatomic, assign) WKWebView *uiWebView;
@property (nonatomic, copy) NSString *jsScheme;
@end
@implementation UIWebViewWrapper {
}
+ (instancetype)webViewWrapper {
return [[[self alloc] init] autorelease];
}
- (instancetype)init {
self = [super init];
if (self) {
self.uiWebView = nil;
self.shouldStartLoading = nullptr;
self.didFinishLoading = nullptr;
self.didFailLoading = nullptr;
}
return self;
}
- (void)dealloc {
self.uiWebView.UIDelegate = nil;
[self.uiWebView removeFromSuperview];
[self.uiWebView release];
self.jsScheme = nil;
[super dealloc];
}
- (void)setupWebView {
if (!self.uiWebView) {
self.uiWebView = [[WKWebView alloc] init];
self.uiWebView.UIDelegate = self;
self.uiWebView.navigationDelegate = self;
}
if (!self.uiWebView.superview) {
//UIView *eaglview = UIApplication.sharedApplication.delegate.window.rootViewController.view;
UIView *eaglview = WarpCocosContent.shareInstance.renderView;
[eaglview addSubview:self.uiWebView];
}
}
- (void)setVisible:(bool)visible {
self.uiWebView.hidden = !visible;
}
- (void)setBounces:(bool)bounces {
self.uiWebView.scrollView.bounces = bounces;
}
- (void)setFrame:(float)x y:(float)y width:(float)width height:(float)height {
if (!self.uiWebView) {
[self setupWebView];
}
CGRect newFrame = CGRectMake(x, y, width, height);
if (!CGRectEqualToRect(self.uiWebView.frame, newFrame)) {
self.uiWebView.frame = newFrame;
}
}
- (void)setJavascriptInterfaceScheme:(const ccstd::string &)scheme {
self.jsScheme = @(scheme.c_str());
}
- (void)loadData:(const ccstd::string &)data MIMEType:(const ccstd::string &)MIMEType textEncodingName:(const ccstd::string &)encodingName baseURL:(const ccstd::string &)baseURL {
auto path = [[NSBundle mainBundle] resourcePath];
path = [path stringByAppendingPathComponent:@(baseURL.c_str())];
auto url = [NSURL fileURLWithPath:path];
[self.uiWebView loadData:[NSData dataWithBytes:data.c_str() length:data.length()]
MIMEType:@(MIMEType.c_str())
characterEncodingName:@(encodingName.c_str())
baseURL:url];
}
- (void)loadHTMLString:(const ccstd::string &)string baseURL:(const ccstd::string &)baseURL {
if (!self.uiWebView) {
[self setupWebView];
}
auto path = [[NSBundle mainBundle] resourcePath];
path = [path stringByAppendingPathComponent:@(baseURL.c_str())];
auto url = [NSURL fileURLWithPath:path];
[self.uiWebView loadHTMLString:@(string.c_str()) baseURL:url];
}
- (void)loadUrl:(const ccstd::string &)urlString {
if (!self.uiWebView) {
[self setupWebView];
}
NSURL *url = [NSURL URLWithString:@(urlString.c_str())];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.uiWebView loadRequest:request];
}
- (void)loadFile:(const ccstd::string &)filePath {
if (!self.uiWebView) {
[self setupWebView];
}
NSURL *url = [NSURL fileURLWithPath:@(filePath.c_str())];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.uiWebView loadRequest:request];
}
- (void)stopLoading {
[self.uiWebView stopLoading];
}
- (void)reload {
[self.uiWebView reload];
}
- (BOOL)canGoForward {
return self.uiWebView.canGoForward;
}
- (BOOL)canGoBack {
return self.uiWebView.canGoBack;
}
- (void)goBack {
[self.uiWebView goBack];
}
- (void)goForward {
[self.uiWebView goForward];
}
- (void)evaluateJS:(const ccstd::string &)js {
if (!self.uiWebView) {
[self setupWebView];
}
[self.uiWebView evaluateJavaScript:@(js.c_str()) completionHandler:nil];
}
- (void)setScalesPageToFit:(const bool)scalesPageToFit {
// TODO: there is not corresponding API in WK.
// https://stackoverflow.com/questions/26295277/wkwebview-equivalent-for-uiwebviews-scalespagetofit/43048514 seems has a solution,
// but it doesn't support setting it dynamically. If we want to set this feature dynamically, then it will be too complex.
}
- (void)setBackgroundTransparent:(const bool)isTransparent {
if (!self.uiWebView) {
[self setupWebView];
}
[self.uiWebView setOpaque:isTransparent ? NO : YES];
[self.uiWebView setBackgroundColor:isTransparent ? [UIColor clearColor] : [UIColor whiteColor]];
}
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSString *url = [[navigationAction request].URL.absoluteString stringByRemovingPercentEncoding];
NSString *scheme = [navigationAction request].URL.scheme;
if ([scheme isEqualToString:self.jsScheme]) {
self.onJsCallback(url.UTF8String);
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
if (self.shouldStartLoading && url) {
if (self.shouldStartLoading(url.UTF8String))
decisionHandler(WKNavigationActionPolicyAllow);
else
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
if (self.didFinishLoading) {
NSString *url = [webView.URL absoluteString];
self.didFinishLoading([url UTF8String]);
}
}
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
if (self.didFailLoading) {
NSString *errorInfo = error.userInfo[NSURLErrorFailingURLStringErrorKey];
if (errorInfo) {
self.didFailLoading([errorInfo UTF8String]);
}
}
}
#pragma WKUIDelegate
// Implement js alert function.
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)())completionHandler {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message
message:nil
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"Ok"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
completionHandler();
}]];
//auto rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
auto rootViewController = WarpCocosContent.shareInstance.gameVCBlock();
[rootViewController presentViewController:alertController
animated:YES
completion:^{
}];
}
@end
namespace cc {
WebViewImpl::WebViewImpl(WebView *webView)
: _uiWebViewWrapper([UIWebViewWrapper webViewWrapper]),
_webView(webView) {
[_uiWebViewWrapper retain];
_uiWebViewWrapper.shouldStartLoading = [this](ccstd::string url) {
if (this->_webView->_onShouldStartLoading) {
return this->_webView->_onShouldStartLoading(this->_webView, url);
}
return true;
};
_uiWebViewWrapper.didFinishLoading = [this](ccstd::string url) {
if (this->_webView->_onDidFinishLoading) {
this->_webView->_onDidFinishLoading(this->_webView, url);
}
};
_uiWebViewWrapper.didFailLoading = [this](ccstd::string url) {
if (this->_webView->_onDidFailLoading) {
this->_webView->_onDidFailLoading(this->_webView, url);
}
};
_uiWebViewWrapper.onJsCallback = [this](ccstd::string url) {
if (this->_webView->_onJSCallback) {
this->_webView->_onJSCallback(this->_webView, url);
}
};
}
WebViewImpl::~WebViewImpl() {
destroy();
}
void WebViewImpl::destroy() {
if (_uiWebViewWrapper != nil) {
[_uiWebViewWrapper release];
_uiWebViewWrapper = nil;
}
}
void WebViewImpl::setJavascriptInterfaceScheme(const ccstd::string &scheme) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper setJavascriptInterfaceScheme:scheme];
}
void WebViewImpl::loadData(const Data &data,
const ccstd::string &MIMEType,
const ccstd::string &encoding,
const ccstd::string &baseURL) {
if (_uiWebViewWrapper == nil) {
return;
}
ccstd::string dataString(reinterpret_cast<char *>(data.getBytes()), static_cast<unsigned int>(data.getSize()));
[_uiWebViewWrapper loadData:dataString MIMEType:MIMEType textEncodingName:encoding baseURL:baseURL];
}
void WebViewImpl::loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper loadHTMLString:string baseURL:baseURL];
}
void WebViewImpl::loadURL(const ccstd::string &url) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper loadUrl:url];
}
void WebViewImpl::loadFile(const ccstd::string &fileName) {
if (_uiWebViewWrapper == nil) {
return;
}
auto fullPath = cc::FileUtils::getInstance()->fullPathForFilename(fileName);
[_uiWebViewWrapper loadFile:fullPath];
}
void WebViewImpl::stopLoading() {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper stopLoading];
}
void WebViewImpl::reload() {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper reload];
}
bool WebViewImpl::canGoBack() {
if (_uiWebViewWrapper == nil) {
return false;
}
return _uiWebViewWrapper.canGoBack;
}
bool WebViewImpl::canGoForward() {
if (_uiWebViewWrapper == nil) {
return false;
}
return _uiWebViewWrapper.canGoForward;
}
void WebViewImpl::goBack() {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper goBack];
}
void WebViewImpl::goForward() {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper goForward];
}
void WebViewImpl::evaluateJS(const ccstd::string &js) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper evaluateJS:js];
}
void WebViewImpl::setBounces(bool bounces) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper setBounces:bounces];
}
void WebViewImpl::setScalesPageToFit(bool scalesPageToFit) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper setScalesPageToFit:scalesPageToFit];
}
void WebViewImpl::setVisible(bool visible) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper setVisible:visible];
}
void WebViewImpl::setFrame(float x, float y, float width, float height) {
if (_uiWebViewWrapper == nil) {
return;
}
auto scaleFactor = [[UIScreen mainScreen] nativeScale];
[_uiWebViewWrapper setFrame:x / scaleFactor
y:y / scaleFactor
width:width / scaleFactor
height:height / scaleFactor];
}
void WebViewImpl::setBackgroundTransparent(bool isTransparent) {
if (_uiWebViewWrapper == nil) {
return;
}
[_uiWebViewWrapper setBackgroundTransparent:isTransparent];
}
} //namespace cc

View File

@@ -0,0 +1,94 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include <cstdint>
#include <iosfwd>
#include "base/Data.h"
#include "base/Macros.h"
namespace cc {
class WebView;
class WebViewImpl final {
public:
explicit WebViewImpl(WebView *webView);
~WebViewImpl();
void destroy();
void setJavascriptInterfaceScheme(const ccstd::string &scheme);
void loadData(const cc::Data &data, const ccstd::string &mimeType,
const ccstd::string &encoding, const ccstd::string &baseURL);
void loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL);
void loadURL(const ccstd::string &url);
void loadFile(const ccstd::string &fileName);
void stopLoading();
void reload();
bool canGoBack();
bool canGoForward();
void goBack();
void goForward();
void evaluateJS(const ccstd::string &js);
void setScalesPageToFit(bool scalesPageToFit);
void setVisible(bool visible);
void setFrame(float x, float y, float width, float height);
void setBounces(bool bounces);
void setBackgroundTransparent(bool isTransparent);
static bool shouldStartLoading(int viewTag, const ccstd::string &url);
static void didFinishLoading(int viewTag, const ccstd::string &url);
static void didFailLoading(int viewTag, const ccstd::string &url);
static void onJsCallback(int viewTag, const ccstd::string &message);
private:
int _viewTag;
WebView *_webView;
};
} // namespace cc

View File

@@ -0,0 +1,302 @@
/****************************************************************************
Copyright (c) 2014-2016 Chukong Technologies Inc.
Copyright (c) 2017-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <cstdlib>
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
#include "WebView-inl.h"
#include "platform/FileUtils.h"
#include "platform/java/jni/JniHelper.h"
#include "cocos/base/Log.h"
static const ccstd::string CLASS_NAME = "com/cocos/lib/CocosWebViewHelper";
#define LOGD CC_LOG_DEBUG
static const ccstd::string S_DEFAULT_BASE_URL = "file:///android_asset/";
static const ccstd::string S_SD_ROOT_BASE_URL = "file://";
static ccstd::string getFixedBaseUrl(const ccstd::string &baseUrl) {
ccstd::string fixedBaseUrl;
if (baseUrl.empty()) {
fixedBaseUrl = S_DEFAULT_BASE_URL;
} else if (baseUrl.find(S_SD_ROOT_BASE_URL) != ccstd::string::npos) {
fixedBaseUrl = baseUrl;
} else if (baseUrl.c_str()[0] != '/') {
if (baseUrl.find("assets/") == 0) {
fixedBaseUrl = S_DEFAULT_BASE_URL + baseUrl.c_str()[7];
} else {
fixedBaseUrl = S_DEFAULT_BASE_URL + baseUrl;
}
} else {
fixedBaseUrl = S_SD_ROOT_BASE_URL + baseUrl;
}
if (fixedBaseUrl.c_str()[fixedBaseUrl.length() - 1] != '/') {
fixedBaseUrl += "/";
}
return fixedBaseUrl;
}
extern "C" {
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: shouldStartLoading
* Signature: (ILjava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL
Java_com_cocos_lib_CocosWebViewHelper_shouldStartLoading(JNIEnv *env, jclass, jint index, //NOLINT
jstring jurl) {
auto charUrl = env->GetStringUTFChars(jurl, nullptr);
ccstd::string url = charUrl;
env->ReleaseStringUTFChars(jurl, charUrl);
return cc::WebViewImpl::shouldStartLoading(index, url);
}
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: didFinishLoading
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_com_cocos_lib_CocosWebViewHelper_didFinishLoading(JNIEnv *env, jclass, jint index, //NOLINT
jstring jurl) {
// LOGD("didFinishLoading");
auto charUrl = env->GetStringUTFChars(jurl, nullptr);
ccstd::string url = charUrl;
env->ReleaseStringUTFChars(jurl, charUrl);
cc::WebViewImpl::didFinishLoading(index, url);
}
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: didFailLoading
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_com_cocos_lib_CocosWebViewHelper_didFailLoading(JNIEnv *env, jclass, jint index, //NOLINT
jstring jurl) {
// LOGD("didFailLoading");
auto charUrl = env->GetStringUTFChars(jurl, nullptr);
ccstd::string url = charUrl;
env->ReleaseStringUTFChars(jurl, charUrl);
cc::WebViewImpl::didFailLoading(index, url);
}
/*
* Class: com_cocos_lib_CocosWebViewHelper
* Method: onJsCallback
* Signature: (ILjava/lang/String;)V
*/
JNIEXPORT void JNICALL
Java_com_cocos_lib_CocosWebViewHelper_onJsCallback(JNIEnv *env, jclass, jint index, //NOLINT
jstring jmessage) {
// LOGD("jsCallback");
auto charMessage = env->GetStringUTFChars(jmessage, nullptr);
ccstd::string message = charMessage;
env->ReleaseStringUTFChars(jmessage, charMessage);
cc::WebViewImpl::onJsCallback(index, message);
}
}
namespace {
int createWebViewJNI() {
cc::JniMethodInfo t;
if (cc::JniHelper::getStaticMethodInfo(t, CLASS_NAME.c_str(), "createWebView", "()I")) {
// LOGD("error: %s,%d",__func__,__LINE__);
jint viewTag = t.env->CallStaticIntMethod(t.classID, t.methodID);
ccDeleteLocalRef(t.env, t.classID);
return viewTag;
}
return -1;
}
ccstd::string getUrlStringByFileName(const ccstd::string &fileName) {
// LOGD("error: %s,%d",__func__,__LINE__);
const ccstd::string basePath("file:///android_asset/");
ccstd::string fullPath = cc::FileUtils::getInstance()->fullPathForFilename(fileName);
const ccstd::string assetsPath("assets/");
ccstd::string urlString;
if (fullPath.find(assetsPath) != ccstd::string::npos) {
urlString = fullPath.replace(fullPath.find_first_of(assetsPath), assetsPath.length(),
basePath);
} else {
urlString = fullPath;
}
return urlString;
}
} // namespace
namespace cc {
static ccstd::unordered_map<int, WebViewImpl *> sWebViewImpls;
WebViewImpl::WebViewImpl(WebView *webView) : _viewTag(-1),
_webView(webView) {
_viewTag = createWebViewJNI();
sWebViewImpls[_viewTag] = this;
}
WebViewImpl::~WebViewImpl() {
destroy();
}
void WebViewImpl::destroy() {
if (_viewTag != -1) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "removeWebView", _viewTag);
auto iter = sWebViewImpls.find(_viewTag);
if (iter != sWebViewImpls.end()) {
sWebViewImpls.erase(iter);
}
_viewTag = -1;
}
}
void WebViewImpl::loadData(const Data &data, const ccstd::string &mimeType,
const ccstd::string &encoding, const ccstd::string &baseURL) {
ccstd::string dataString(reinterpret_cast<char *>(data.getBytes()),
static_cast<unsigned int>(data.getSize()));
JniHelper::callStaticVoidMethod(CLASS_NAME, "setJavascriptInterfaceScheme", _viewTag,
dataString, mimeType, encoding, baseURL);
}
void WebViewImpl::loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "loadHTMLString", _viewTag, string, baseURL);
}
void WebViewImpl::loadURL(const ccstd::string &url) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "loadUrl", _viewTag, url);
}
void WebViewImpl::loadFile(const ccstd::string &fileName) {
auto fullPath = getUrlStringByFileName(fileName);
JniHelper::callStaticVoidMethod(CLASS_NAME, "loadFile", _viewTag, fullPath);
}
void WebViewImpl::stopLoading() {
JniHelper::callStaticVoidMethod(CLASS_NAME, "stopLoading", _viewTag);
}
void WebViewImpl::reload() {
JniHelper::callStaticVoidMethod(CLASS_NAME, "reload", _viewTag);
}
bool WebViewImpl::canGoBack() {
return JniHelper::callStaticBooleanMethod(CLASS_NAME, "canGoBack", _viewTag);
}
bool WebViewImpl::canGoForward() {
return JniHelper::callStaticBooleanMethod(CLASS_NAME, "canGoForward", _viewTag);
}
void WebViewImpl::goBack() {
JniHelper::callStaticVoidMethod(CLASS_NAME, "goBack", _viewTag);
}
void WebViewImpl::goForward() {
JniHelper::callStaticVoidMethod(CLASS_NAME, "goForward", _viewTag);
}
void WebViewImpl::setJavascriptInterfaceScheme(const ccstd::string &scheme) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "setJavascriptInterfaceScheme", _viewTag,
scheme);
}
void WebViewImpl::evaluateJS(const ccstd::string &js) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "evaluateJS", _viewTag, js);
}
void WebViewImpl::setScalesPageToFit(bool scalesPageToFit) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "setScalesPageToFit", _viewTag, scalesPageToFit);
}
bool WebViewImpl::shouldStartLoading(int viewTag, const ccstd::string &url) {
bool allowLoad = true;
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onShouldStartLoading) {
allowLoad = webView->_onShouldStartLoading(webView, url);
}
}
return allowLoad;
}
void WebViewImpl::didFinishLoading(int viewTag, const ccstd::string &url) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onDidFinishLoading) {
webView->_onDidFinishLoading(webView, url);
}
}
}
void WebViewImpl::didFailLoading(int viewTag, const ccstd::string &url) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onDidFailLoading) {
webView->_onDidFailLoading(webView, url);
}
}
}
void WebViewImpl::onJsCallback(int viewTag, const ccstd::string &message) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message);
}
}
}
void WebViewImpl::setVisible(bool visible) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "setVisible", _viewTag, visible);
}
void WebViewImpl::setFrame(float x, float y, float width, float height) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "setWebViewRect", _viewTag,
static_cast<int>(x), static_cast<int>(y), static_cast<int>(width), static_cast<int>(height));
}
void WebViewImpl::setBounces(bool bounces) {
// empty function as this was mainly a fix for iOS
}
void WebViewImpl::setBackgroundTransparent(bool isTransparent) {
JniHelper::callStaticVoidMethod(CLASS_NAME, "setBackgroundTransparent", _viewTag,
isTransparent);
}
} //namespace cc

View File

@@ -0,0 +1,313 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include <cstdlib>
#include "base/std/container/string.h"
#include "base/std/container/unordered_map.h"
#include "WebView-inl.h"
#include "platform/FileUtils.h"
#include "platform/openharmony/napi/NapiHelper.h"
#include "WebViewImpl-openharmony.h"
#include "cocos/base/Log.h"
static const ccstd::string S_DEFAULT_BASE_URL = "file:///openharmony_asset/";
static const ccstd::string S_SD_ROOT_BASE_URL = "file://";
static ccstd::string getFixedBaseUrl(const ccstd::string &baseUrl) {
ccstd::string fixedBaseUrl;
if (baseUrl.empty()) {
fixedBaseUrl = S_DEFAULT_BASE_URL;
} else if (baseUrl.find(S_SD_ROOT_BASE_URL) != ccstd::string::npos) {
fixedBaseUrl = baseUrl;
} else if (baseUrl.c_str()[0] != '/') {
if (baseUrl.find("assets/") == 0) {
fixedBaseUrl = S_DEFAULT_BASE_URL + baseUrl.c_str()[7];
} else {
fixedBaseUrl = S_DEFAULT_BASE_URL + baseUrl;
}
} else {
fixedBaseUrl = S_SD_ROOT_BASE_URL + baseUrl;
}
if (fixedBaseUrl.c_str()[fixedBaseUrl.length() - 1] != '/') {
fixedBaseUrl += "/";
}
return fixedBaseUrl;
}
ccstd::string getUrlStringByFileName(const ccstd::string &fileName) {
// LOGD("error: %s,%d",__func__,__LINE__);
const ccstd::string basePath(S_DEFAULT_BASE_URL);
ccstd::string fullPath = cc::FileUtils::getInstance()->fullPathForFilename(fileName);
const ccstd::string assetsPath("assets/");
ccstd::string urlString;
if (fullPath.find(assetsPath) != ccstd::string::npos) {
urlString = fullPath.replace(fullPath.find_first_of(assetsPath), assetsPath.length(),
basePath);
} else {
urlString = fullPath;
}
return urlString;
}
namespace cc {
static int32_t kWebViewTag = 0;
static ccstd::unordered_map<int, WebViewImpl *> sWebViewImpls;
WebViewImpl::WebViewImpl(WebView *webView) : _viewTag(-1),
_webView(webView) {
_viewTag = kWebViewTag++;
NapiHelper::postMessageToUIThread("createWebView", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
sWebViewImpls[_viewTag] = this;
}
WebViewImpl::~WebViewImpl() {
destroy();
}
void WebViewImpl::destroy() {
if (_viewTag != -1) {
NapiHelper::postMessageToUIThread("removeWebView", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
auto iter = sWebViewImpls.find(_viewTag);
if (iter != sWebViewImpls.end()) {
sWebViewImpls.erase(iter);
}
_viewTag = -1;
}
}
void WebViewImpl::loadData(const Data &data, const ccstd::string &mimeType,
const ccstd::string &encoding, const ccstd::string &baseURL) {
ccstd::string dataString(reinterpret_cast<char *>(data.getBytes()),
static_cast<unsigned int>(data.getSize()));
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["contents"] = Napi::String::New(env, dataString);
args["mimeType"] = Napi::String::New(env, mimeType);
args["encoding"] = Napi::String::New(env, encoding);
args["baseUrl"] = Napi::String::New(env, baseURL);
NapiHelper::postMessageToUIThread("loadData", args);
}
void WebViewImpl::loadHTMLString(const ccstd::string &string, const ccstd::string &baseURL) {
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["contents"] = Napi::String::New(env, string);
args["baseUrl"] = Napi::String::New(env, baseURL);
NapiHelper::postMessageToUIThread("loadHTMLString", args);
}
void WebViewImpl::loadURL(const ccstd::string &url) {
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["url"] = Napi::String::New(env, url);
NapiHelper::postMessageToUIThread("loadUrl", args);
}
void WebViewImpl::loadFile(const ccstd::string &fileName) {
auto fullPath = getUrlStringByFileName(fileName);
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["url"] = Napi::String::New(env, fullPath);
NapiHelper::postMessageToUIThread("loadUrl", args);
}
void WebViewImpl::stopLoading() {
NapiHelper::postMessageToUIThread("stopLoading", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
}
void WebViewImpl::reload() {
NapiHelper::postMessageToUIThread("reload", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
}
bool WebViewImpl::canGoBack() {
// TODO(qgh):OpenHarmony does not support this interface.
return true;
}
bool WebViewImpl::canGoForward() {
// TODO(qgh):OpenHarmony does not support this interface.
return true;
}
void WebViewImpl::goBack() {
NapiHelper::postMessageToUIThread("goBack", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
}
void WebViewImpl::goForward() {
NapiHelper::postMessageToUIThread("goForward", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
}
void WebViewImpl::setJavascriptInterfaceScheme(const ccstd::string &scheme) {
// TODO(qgh):OpenHarmony does not support this interface.
}
void WebViewImpl::evaluateJS(const ccstd::string &js) {
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["jsContents"] = Napi::String::New(env, js);
NapiHelper::postMessageToUIThread("evaluateJS", args);
}
void WebViewImpl::setScalesPageToFit(bool scalesPageToFit) {
NapiHelper::postMessageToUIThread("setScalesPageToFit", Napi::Number::New(NapiHelper::getWorkerEnv(), static_cast<double>(_viewTag)));
}
bool WebViewImpl::shouldStartLoading(int viewTag, const ccstd::string &url) {
bool allowLoad = true;
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onShouldStartLoading) {
allowLoad = webView->_onShouldStartLoading(webView, url);
}
}
return allowLoad;
}
void WebViewImpl::didFinishLoading(int viewTag, const ccstd::string &url) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onDidFinishLoading) {
webView->_onDidFinishLoading(webView, url);
}
}
}
void WebViewImpl::didFailLoading(int viewTag, const ccstd::string &url) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onDidFailLoading) {
webView->_onDidFailLoading(webView, url);
}
}
}
void WebViewImpl::onJsCallback(int viewTag, const ccstd::string &message) {
auto it = sWebViewImpls.find(viewTag);
if (it != sWebViewImpls.end()) {
auto webView = it->second->_webView;
if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message);
}
}
}
void WebViewImpl::setVisible(bool visible) {
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["visible"] = Napi::Boolean::New(env, visible);
NapiHelper::postMessageToUIThread("setVisible", args);
}
void WebViewImpl::setFrame(float x, float y, float width, float height) {
auto env = NapiHelper::getWorkerEnv();
auto args = Napi::Object::New(env);
args["tag"] = Napi::Number::New(env, static_cast<double>(_viewTag));
args["x"] = Napi::Number::New(env, x);
args["y"] = Napi::Number::New(env, y);
args["w"] = Napi::Number::New(env, width);
args["h"] = Napi::Number::New(env, height);
NapiHelper::postMessageToUIThread("setWebViewRect", args);
}
void WebViewImpl::setBounces(bool bounces) {
// empty function as this was mainly a fix for iOS
}
void WebViewImpl::setBackgroundTransparent(bool isTransparent) {
// TODO(qgh):OpenHarmony is not supported at this time
}
static void getViewTagAndUrlFromCallbackInfo(const Napi::CallbackInfo &info, int32_t *viewTag, ccstd::string *url) {
auto env = info.Env();
if (info.Length() != 2) {
Napi::Error::New(env, "napiShouldStartLoading, 2 arguments expected").ThrowAsJavaScriptException();
return;
}
auto arg0 = info[0].As<Napi::Number>();
auto arg1 = info[1].As<Napi::String>();
if (env.IsExceptionPending()) {
return;
}
*viewTag = arg0.Int32Value();
*url = arg1.Utf8Value();
}
void OpenHarmonyWebView::napiShouldStartLoading(const Napi::CallbackInfo &info) {
int32_t viewTag = 0;
ccstd::string url;
getViewTagAndUrlFromCallbackInfo(info, &viewTag, &url);
WebViewImpl::shouldStartLoading(viewTag, url);
}
void OpenHarmonyWebView::napiFinishLoading(const Napi::CallbackInfo &info) {
int32_t viewTag = 0;
ccstd::string url;
getViewTagAndUrlFromCallbackInfo(info, &viewTag, &url);
WebViewImpl::didFinishLoading(viewTag, url);
}
void OpenHarmonyWebView::napiFailLoading(const Napi::CallbackInfo &info) {
int32_t viewTag = 0;
ccstd::string url;
getViewTagAndUrlFromCallbackInfo(info, &viewTag, &url);
WebViewImpl::didFailLoading(viewTag, url);
}
void OpenHarmonyWebView::napiJsCallback(const Napi::CallbackInfo &info) {
int32_t viewTag = 0;
ccstd::string url;
getViewTagAndUrlFromCallbackInfo(info, &viewTag, &url);
WebViewImpl::onJsCallback(viewTag, url);
}
} //namespace cc

View File

@@ -0,0 +1,41 @@
/****************************************************************************
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#pragma once
#include "platform/openharmony/napi/NapiHelper.h"
#include "ui/webview/WebViewImpl-java.h"
namespace cc {
class OpenHarmonyWebView {
public:
static void napiShouldStartLoading(const Napi::CallbackInfo &info);
static void napiFinishLoading(const Napi::CallbackInfo &info);
static void napiFailLoading(const Napi::CallbackInfo &info);
static void napiJsCallback(const Napi::CallbackInfo &info);
};
} //namespace cc