mirror of
https://github.com/chenasraf/webview_cef.git
synced 2026-05-17 17:48:07 +00:00
support evaluateJavascript
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user