support evaluateJavascript

This commit is contained in:
SinyimZhi
2024-01-15 19:37:03 +08:00
committed by GitHub
parent 2d1938930b
commit 9dc814fdce
9 changed files with 103 additions and 24 deletions

View File

@@ -150,6 +150,11 @@ void WebviewApp::OnWebKitInitialized()
}
}
external.EvaluateCallback = (nReqID, result) => {
native function EvaluateCallback();
EvaluateCallback(nReqID, result);
}
external.StartRequest = (nReqID, strCmd, strCallBack, strArgs, strLog) => {
native function StartRequest();
StartRequest(nReqID, strCmd, strCallBack, strArgs, strLog);

View File

@@ -7,6 +7,7 @@
#include <sstream>
#include <string>
#include <iostream>
#include <chrono>
#include "include/base/cef_callback.h"
#include "include/cef_app.h"
@@ -64,6 +65,17 @@ bool WebviewHandler::OnProcessMessageReceived(
onJavaScriptChannelMessage(
fun_name,param,std::to_string(js_callback_id),std::to_string(frame->GetIdentifier()));
}
else if(message_name == kEvaluateCallbackMessage){
CefString callbackId = message->GetArgumentList()->GetString(0);
CefString param = message->GetArgumentList()->GetString(1);
if(!callbackId.empty() && !param.empty()){
auto it = js_callbacks_.find(callbackId.ToString());
if(it != js_callbacks_.end()){
it->second(param.ToString());
js_callbacks_.erase(it);
}
}
}
return false;
}
@@ -373,24 +385,24 @@ void WebviewHandler::deleteCookie(const std::string& domain, const std::string&
}
}
bool WebviewHandler::visitAllCookies(std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback){
void WebviewHandler::visitAllCookies(std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback){
CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(nullptr);
if (!manager)
{
return false;
return;
}
CefRefPtr<WebviewCookieVisitor> cookieVisitor = new WebviewCookieVisitor();
cookieVisitor->setOnVisitComplete(callback);
return manager->VisitAllCookies(cookieVisitor);
manager->VisitAllCookies(cookieVisitor);
}
bool WebviewHandler::visitUrlCookies(const std::string& domain, const bool& isHttpOnly, std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback){
void WebviewHandler::visitUrlCookies(const std::string& domain, const bool& isHttpOnly, std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback){
CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(nullptr);
if (!manager)
{
return false;
return;
}
CefRefPtr<WebviewCookieVisitor> cookieVisitor = new WebviewCookieVisitor();
@@ -398,10 +410,10 @@ bool WebviewHandler::visitUrlCookies(const std::string& domain, const bool& isHt
std::string httpDomain = "https://" + domain + "/cookiestorage";
return manager->VisitUrlCookies(httpDomain, isHttpOnly, cookieVisitor);
manager->VisitUrlCookies(httpDomain, isHttpOnly, cookieVisitor);
}
bool WebviewHandler::setJavaScriptChannels(const std::vector<std::string> channels)
void WebviewHandler::setJavaScriptChannels(const std::vector<std::string> channels)
{
std::string extensionCode = "";
for(auto& channel : channels)
@@ -411,10 +423,10 @@ bool WebviewHandler::setJavaScriptChannels(const std::vector<std::string> channe
extensionCode += channel;
extensionCode += "',e,r)};";
}
return executeJavaScript(extensionCode);
executeJavaScript(extensionCode);
}
bool WebviewHandler::sendJavaScriptChannelCallBack(const bool error, const std::string result, const std::string callbackId, const std::string frameId)
void WebviewHandler::sendJavaScriptChannelCallBack(const bool error, const std::string result, const std::string callbackId, const std::string frameId)
{
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kExecuteJsCallbackMessage);
CefRefPtr<CefListValue> args = message->GetArgumentList();
@@ -427,13 +439,18 @@ bool WebviewHandler::sendJavaScriptChannelCallBack(const bool error, const std::
if (frame->GetIdentifier() == atoll(frameId.c_str()))
{
frame->SendProcessMessage(PID_RENDERER, message);
return true;
}
}
return false;
}
bool WebviewHandler::executeJavaScript(const std::string code)
static std::string GetCallbackId()
{
auto time = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
time_t timestamp = time.time_since_epoch().count();
return std::to_string(timestamp);
}
void WebviewHandler::executeJavaScript(const std::string code, std::function<void(std::string)> callback)
{
if(!code.empty())
{
@@ -442,13 +459,21 @@ bool WebviewHandler::executeJavaScript(const std::string code)
if ((*bit).get()) {
CefRefPtr<CefFrame> frame = (*bit)->GetMainFrame();
if (frame) {
frame->ExecuteJavaScript(code, frame->GetURL(), 0);
return true;
std::string finalCode = code;
if(callback != nullptr){
std::string callbackId = GetCallbackId();
finalCode = "external.EvaluateCallback('";
finalCode += callbackId;
finalCode += "',(function(){return ";
finalCode += code;
finalCode += "})());";
js_callbacks_[callbackId] = callback;
}
frame->ExecuteJavaScript(finalCode, frame->GetURL(), 0);
}
}
}
}
return false;
}
void WebviewHandler::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect &rect) {

View File

@@ -9,6 +9,7 @@
#include <functional>
#include <list>
#include <unordered_map>
#include "webview_cookieVisitor.h"
@@ -122,12 +123,12 @@ public:
void setCookie(const std::string& domain, const std::string& key, const std::string& value);
void deleteCookie(const std::string& domain, const std::string& key);
bool visitAllCookies(std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback);
bool visitUrlCookies(const std::string& domain, const bool& isHttpOnly, std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback);
void visitAllCookies(std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback);
void visitUrlCookies(const std::string& domain, const bool& isHttpOnly, std::function<void(std::map<std::string, std::map<std::string, std::string>>)> callback);
bool setJavaScriptChannels(const std::vector<std::string> channels);
bool sendJavaScriptChannelCallBack(const bool error, const std::string result, const std::string callbackId, const std::string frameId);
bool executeJavaScript(const std::string code);
void setJavaScriptChannels(const std::vector<std::string> channels);
void sendJavaScriptChannelCallBack(const bool error, const std::string result, const std::string callbackId, const std::string frameId);
void executeJavaScript(const std::string code, std::function<void(std::string)> callback = nullptr);
private:
uint32_t width = 1;
@@ -138,6 +139,8 @@ private:
// List of existing browser windows. Only accessed on the CEF UI thread.
typedef std::list<CefRefPtr<CefBrowser>> BrowserList;
BrowserList browser_list_;
std::unordered_map<std::string, std::function<void(std::string)>> js_callbacks_;
// Include the default reference counting implementation.
IMPLEMENT_REFCOUNTING(WebviewHandler);

View File

@@ -86,6 +86,17 @@ bool CefJSHandler::Execute(const CefString& name,
int reqID = CefJSBridge::GetNextReqID();
retval = CefV8Value::CreateInt(reqID);
}
else if (name == "EvaluateCallback") {
CefString callbackId = arguments[0]->GetStringValue();
CefString result = arguments[1]->GetStringValue();
if (!js_bridge_->EvaluateCallback(callbackId, result)) {
std::ostringstream strStream;
strStream << "Failed to callback: " << callbackId.c_str() << ".";
strStream.flush();
exception = strStream.str();
}
}
else {
exception = "NativeHost no this fun.";
}
@@ -125,6 +136,22 @@ bool CefJSBridge::StartRequest(int reqId,
return false;
}
bool CefJSBridge::EvaluateCallback(const CefString& callbackId, const CefString& result){
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
if(context){
CefRefPtr<CefFrame> frame = context->GetFrame();
if(frame){
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kEvaluateCallbackMessage);
message->GetArgumentList()->SetString(0, callbackId);
message->GetArgumentList()->SetString(1, result);
frame->SendProcessMessage(PID_BROWSER, message);
return true;
}
}
return false;
}
int CefJSBridge::GetNextReqID()
{
long nRet = ++s_nReqID;

View File

@@ -9,6 +9,7 @@
static const char kJSCallCppFunctionMessage[] = "JSCallCppFunction"; //js call c++ message
static const char kExecuteJsCallbackMessage[] = "ExecuteJsCallback"; //c++ call js message
static const char kEvaluateCallbackMessage[] = "EvaluateCallback"; //js callback c++ message
static const char kFocusedNodeChangedMessage[] = "FocusedNodeChanged"; //elements that capture focus in web pages changed message
class CefJSBridge
@@ -22,6 +23,7 @@ public:
public:
static int GetNextReqID();
bool StartRequest(int reqId, const CefString& strCmd, const CefString& strCallback, const CefString& strArgs);
bool EvaluateCallback(const CefString& callbackId, const CefString& result);
bool CallCppFunction(const CefString& function_name, const CefString& params, CefRefPtr<CefV8Value> callback, CefRefPtr<CefV8Value> rawdata);
void RemoveCallbackFuncWithFrame(CefRefPtr<CefFrame> frame);

View File

@@ -219,6 +219,14 @@ namespace webview_cef {
handler.get()->executeJavaScript(code);
result(1, nullptr);
}
else if(name.compare("evaluateJavascript") == 0){
const auto code = webview_value_get_string(webview_value_get_list_value(values, 0));
handler.get()->executeJavaScript(code, [=](std::string values){
WValue* retValue = webview_value_new_string(values.c_str());
result(1, retValue);
webview_value_unref(retValue);
});
}
else {
result = 0;
}

View File

@@ -59,7 +59,8 @@ class _MyAppState extends State<MyApp> {
//normal JavaScriptChannels
await _controller.setJavaScriptChannels(jsChannels);
//also you can build your own jssdk by execute JavaScript code to CEF
await _controller.executeJavaScript("function abc(e){console.log(e)}");
await _controller.executeJavaScript("function abc(e){return 'abc:'+ e}");
_controller.evaluateJavascript("abc('test')").then((value) => print(value));
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.

View File

@@ -194,7 +194,7 @@ class WebViewController extends ValueNotifier<bool> {
'sendJavaScriptChannelCallBack', [error, result, callbackId, frameId]);
}
Future<dynamic> executeJavaScript(String code) async {
Future<void> executeJavaScript(String code) async {
if (_isDisposed) {
return;
}
@@ -202,6 +202,14 @@ class WebViewController extends ValueNotifier<bool> {
return _pluginChannel.invokeMethod('executeJavaScript', [code]);
}
Future<dynamic> evaluateJavascript(String code) async {
if (_isDisposed) {
return;
}
assert(value);
return _pluginChannel.invokeMethod('evaluateJavascript', [code]);
}
/// Moves the virtual cursor to [position].
Future<void> _cursorMove(Offset position) async {
if (_isDisposed) {

View File

@@ -288,9 +288,9 @@ FlutterMethodChannel* f_channel;
result([NSNumber numberWithLong:textureId]);
}else{
WValue *encodeArgs = [self encode_flvalue_to_wvalue:call.arguments];
int ret = webview_cef::HandleMethodCall(name, encodeArgs, [=](int ret, WValue* args){
webview_cef::HandleMethodCall(name, encodeArgs, [=](int ret, WValue* args){
if(ret != 0){
result([self encode_wvalue_to_flvalue:args])
result([self encode_wvalue_to_flvalue:args]);
}
else{
result(nil);