2019-04-19 17:19:57 +08:00
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "cef_js_bridge.h"
|
|
|
|
|
#include "ipc_string_define.h"
|
|
|
|
|
|
|
|
|
|
namespace nim_cef {
|
|
|
|
|
|
|
|
|
|
CefJSBridge::CefJSBridge()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CefJSBridge::~CefJSBridge()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::CallCppFunction(const CefString& function_name, const CefString& params, CefRefPtr<CefV8Value> callback)
|
|
|
|
|
{
|
|
|
|
|
auto it = render_callback_.find(js_callback_id_);
|
|
|
|
|
if (it == render_callback_.cend())
|
|
|
|
|
{
|
|
|
|
|
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
|
|
|
|
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kCallCppFunctionMessage);
|
|
|
|
|
|
|
|
|
|
message->GetArgumentList()->SetString(0, function_name);
|
|
|
|
|
message->GetArgumentList()->SetString(1, params);
|
|
|
|
|
message->GetArgumentList()->SetInt(2, js_callback_id_);
|
|
|
|
|
|
|
|
|
|
render_callback_.emplace(js_callback_id_++, std::make_pair(context, callback));
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2> browser <20><><EFBFBD><EFBFBD>
|
|
|
|
|
CefRefPtr<CefBrowser> browser = context->GetBrowser();
|
|
|
|
|
browser->SendProcessMessage(PID_BROWSER, message);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CefJSBridge::RemoveCallbackFuncWithFrame(CefRefPtr<CefFrame> frame)
|
|
|
|
|
{
|
|
|
|
|
if (!render_callback_.empty())
|
|
|
|
|
{
|
|
|
|
|
for (auto it = render_callback_.begin(); it != render_callback_.end();)
|
|
|
|
|
{
|
|
|
|
|
if (it->second.first->IsSame(frame->GetV8Context()))
|
|
|
|
|
{
|
|
|
|
|
it = render_callback_.erase(it);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::ExecuteJSCallbackFunc(int js_callback_id, bool has_error, const CefString& json_result)
|
|
|
|
|
{
|
|
|
|
|
auto it = render_callback_.find(js_callback_id);
|
|
|
|
|
if (it != render_callback_.cend())
|
|
|
|
|
{
|
|
|
|
|
auto context = it->second.first;
|
|
|
|
|
auto callback = it->second.second;
|
|
|
|
|
|
|
|
|
|
if (context.get() && callback.get())
|
|
|
|
|
{
|
|
|
|
|
context->Enter();
|
|
|
|
|
|
|
|
|
|
CefV8ValueList arguments;
|
|
|
|
|
|
|
|
|
|
// <20><>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD><C7BA><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>ɹ<EFBFBD>
|
|
|
|
|
arguments.push_back(CefV8Value::CreateBool(has_error));
|
|
|
|
|
|
|
|
|
|
// <20>ڶ<EFBFBD><DAB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Я<EFBFBD><D0AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD>кص<F3B7B5BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
CefV8ValueList json_parse_args;
|
|
|
|
|
json_parse_args.push_back(CefV8Value::CreateString(json_result));
|
|
|
|
|
CefRefPtr<CefV8Value> json_parse = context->GetGlobal()->GetValue("JSON")->GetValue("parse");
|
|
|
|
|
CefRefPtr<CefV8Value> json_object = json_parse->ExecuteFunction(NULL, json_parse_args);
|
|
|
|
|
arguments.push_back(json_object);
|
|
|
|
|
|
|
|
|
|
// ִ<><D6B4> JS <20><><EFBFBD><EFBFBD>
|
|
|
|
|
CefRefPtr<CefV8Value> retval = callback->ExecuteFunction(NULL, arguments);
|
|
|
|
|
if (retval.get())
|
|
|
|
|
{
|
|
|
|
|
if (retval->IsBool())
|
|
|
|
|
{
|
|
|
|
|
retval->GetBoolValue();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context->Exit();
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD>б<EFBFBD><D0B1><EFBFBD><EFBFBD>Ƴ<EFBFBD> callback <20><><EFBFBD><EFBFBD>
|
|
|
|
|
render_callback_.erase(js_callback_id);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::RegisterJSFunc(const CefString& function_name, CefRefPtr<CefV8Value> function, bool replace/* = false*/)
|
|
|
|
|
{
|
|
|
|
|
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
|
|
|
|
CefRefPtr<CefFrame> frame = context->GetFrame();
|
|
|
|
|
|
|
|
|
|
if (replace)
|
|
|
|
|
{
|
|
|
|
|
render_registered_function_.emplace(std::make_pair(function_name, frame->GetIdentifier()), function);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto it = render_registered_function_.find(std::make_pair(function_name, frame->GetIdentifier()));
|
|
|
|
|
if (it == render_registered_function_.cend())
|
|
|
|
|
{
|
|
|
|
|
render_registered_function_.emplace(std::make_pair(function_name, frame->GetIdentifier()), function);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CefJSBridge::UnRegisterJSFunc(const CefString& function_name, CefRefPtr<CefFrame> frame)
|
|
|
|
|
{
|
|
|
|
|
render_registered_function_.erase(std::make_pair(function_name, frame->GetIdentifier()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CefJSBridge::UnRegisterJSFuncWithFrame(CefRefPtr<CefFrame> frame)
|
|
|
|
|
{
|
|
|
|
|
// <20><><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD>ÿһ<C3BF><D2BB> render <20><> browser <20><><EFBFBD>̶<EFBFBD><CCB6><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>ģʽ
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȡ<EFBFBD><C8A1> browser <20><><EFBFBD><EFBFBD>ȫ<EFBFBD><C8AB>Ψһ<CEA8>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>Ը<EFBFBD><D4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> browser <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD> frame <20><> context
|
|
|
|
|
auto browser = frame->GetBrowser();
|
|
|
|
|
|
|
|
|
|
if (!render_registered_function_.empty())
|
|
|
|
|
{
|
|
|
|
|
for (auto it = render_registered_function_.begin(); it != render_registered_function_.end();)
|
|
|
|
|
{
|
|
|
|
|
auto child_frame = browser->GetFrame(it->first.second);
|
|
|
|
|
if (child_frame.get() && child_frame->GetV8Context()->IsSame(frame->GetV8Context()))
|
|
|
|
|
{
|
|
|
|
|
it = render_registered_function_.erase(it);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
it++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::ExecuteJSFunc(const CefString& function_name, const CefString& json_params, CefRefPtr<CefFrame> frame, int cpp_callback_id)
|
|
|
|
|
{
|
|
|
|
|
auto it = render_registered_function_.find(std::make_pair(function_name, frame->GetIdentifier()));
|
|
|
|
|
if (it != render_registered_function_.cend())
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
auto context = frame->GetV8Context();
|
|
|
|
|
auto function = it->second;
|
|
|
|
|
|
|
|
|
|
if (context.get() && function.get())
|
|
|
|
|
{
|
|
|
|
|
context->Enter();
|
|
|
|
|
|
|
|
|
|
CefV8ValueList arguments;
|
|
|
|
|
|
|
|
|
|
// <20><> C++ <20><><EFBFBD>ݹ<EFBFBD><DDB9><EFBFBD><EFBFBD><EFBFBD> JSON ת<><D7AA><EFBFBD><EFBFBD> Object
|
|
|
|
|
CefV8ValueList json_parse_args;
|
|
|
|
|
json_parse_args.push_back(CefV8Value::CreateString(json_params));
|
|
|
|
|
CefRefPtr<CefV8Value> json_object = context->GetGlobal()->GetValue("JSON");
|
|
|
|
|
CefRefPtr<CefV8Value> json_parse = json_object->GetValue("parse");
|
|
|
|
|
CefRefPtr<CefV8Value> json_stringify = json_object->GetValue("stringify");
|
|
|
|
|
CefRefPtr<CefV8Value> json_object_args = json_parse->ExecuteFunction(NULL, json_parse_args);
|
|
|
|
|
arguments.push_back(json_object_args);
|
|
|
|
|
|
|
|
|
|
// ִ<>лص<D0BB><D8B5><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
CefRefPtr<CefV8Value> retval = function->ExecuteFunction(NULL, arguments);
|
|
|
|
|
if (retval.get() && retval->IsObject())
|
|
|
|
|
{
|
|
|
|
|
// <20>ظ<EFBFBD><D8B8><EFBFBD><EFBFBD><EFBFBD> JS <20><><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>ֵ
|
|
|
|
|
CefV8ValueList json_stringify_args;
|
|
|
|
|
json_stringify_args.push_back(retval);
|
|
|
|
|
CefRefPtr<CefV8Value> json_string = json_stringify->ExecuteFunction(NULL, json_stringify_args);
|
|
|
|
|
CefString str = json_string->GetStringValue();
|
|
|
|
|
|
|
|
|
|
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kExecuteCppCallbackMessage);
|
|
|
|
|
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
|
|
|
|
args->SetString(0, json_string->GetStringValue());
|
|
|
|
|
args->SetInt(1, cpp_callback_id);
|
2019-08-11 19:49:39 +08:00
|
|
|
|
context->GetBrowser()->SendProcessMessage(PID_BROWSER, message);
|
2019-04-19 17:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
context->Exit();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::CallJSFunction(const CefString& js_function_name, const CefString& params, CefRefPtr<CefFrame> frame, CallJsFunctionCallback callback)
|
|
|
|
|
{
|
|
|
|
|
if (!frame.get())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto it = browser_callback_.find(cpp_callback_id_);
|
|
|
|
|
if (it == browser_callback_.cend())
|
|
|
|
|
{
|
|
|
|
|
browser_callback_.emplace(cpp_callback_id_, callback);
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ<EFBFBD><CFA2> render Ҫ<><D2AA>ִ<EFBFBD><D6B4>һ<EFBFBD><D2BB> js function
|
|
|
|
|
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kCallJsFunctionMessage);
|
|
|
|
|
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
|
|
|
|
args->SetString(0, js_function_name);
|
|
|
|
|
args->SetString(1, params);
|
|
|
|
|
args->SetInt(2, cpp_callback_id_++);
|
|
|
|
|
args->SetInt(3, (int)(frame->GetIdentifier()));
|
|
|
|
|
|
|
|
|
|
frame->GetBrowser()->SendProcessMessage(PID_RENDERER, message);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::ExecuteCppCallbackFunc(int cpp_callback_id, const CefString& json_string)
|
|
|
|
|
{
|
|
|
|
|
auto it = browser_callback_.find(cpp_callback_id);
|
|
|
|
|
if (it != browser_callback_.cend())
|
|
|
|
|
{
|
|
|
|
|
auto callback = it->second;
|
|
|
|
|
if (callback)
|
|
|
|
|
{
|
2019-09-20 16:27:58 +08:00
|
|
|
|
nbase::ThreadManager::PostTask(kThreadMain, [=]() { callback(json_string); });
|
2019-04-19 17:19:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ִ<><D6B4><EFBFBD><EFBFBD><EFBFBD>ɺ<EFBFBD><C9BA>ӻ<EFBFBD><D3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƴ<EFBFBD>
|
|
|
|
|
browser_callback_.erase(cpp_callback_id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::RegisterCppFunc(const CefString& function_name, CppFunction function, CefRefPtr<CefBrowser> browser, bool replace /*= false*/)
|
|
|
|
|
{
|
|
|
|
|
if (replace)
|
|
|
|
|
{
|
|
|
|
|
browser_registered_function_.emplace(std::make_pair(function_name, browser ? browser->GetIdentifier() : -1), function);// = ;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto it = browser_registered_function_.find(std::make_pair(function_name, browser ? browser->GetIdentifier() : -1));
|
|
|
|
|
if (it == browser_registered_function_.cend())
|
|
|
|
|
{
|
|
|
|
|
browser_registered_function_.emplace(std::make_pair(function_name, browser ? browser->GetIdentifier() : -1), function);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CefJSBridge::UnRegisterCppFunc(const CefString& function_name, CefRefPtr<CefBrowser> browser)
|
|
|
|
|
{
|
|
|
|
|
browser_registered_function_.erase(std::make_pair(function_name, browser ? browser->GetIdentifier() : -1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CefJSBridge::ExecuteCppFunc(const CefString& function_name, const CefString& params, int js_callback_id, CefRefPtr<CefBrowser> browser)
|
|
|
|
|
{
|
|
|
|
|
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(kExecuteJsCallbackMessage);
|
|
|
|
|
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
|
|
|
|
|
|
|
|
|
auto it = browser_registered_function_.find(std::make_pair(function_name, browser->GetIdentifier()));
|
|
|
|
|
if (it != browser_registered_function_.cend())
|
|
|
|
|
{
|
|
|
|
|
auto function = it->second;
|
2019-09-20 16:27:58 +08:00
|
|
|
|
nbase::ThreadManager::PostTask(kThreadMain, [=]() {
|
2019-04-19 17:19:57 +08:00
|
|
|
|
function(params, [=](bool has_error, const std::string& json_result) {
|
|
|
|
|
// <20><><EFBFBD>Դ<EFBFBD><D4B4>룬<EFBFBD><EBA3AC>Ҫ<EFBFBD><D2AA>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
args->SetInt(0, js_callback_id);
|
|
|
|
|
args->SetBool(1, has_error);
|
|
|
|
|
args->SetString(2, json_result);
|
|
|
|
|
browser->SendProcessMessage(PID_RENDERER, message);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it = browser_registered_function_.find(std::make_pair(function_name, -1));
|
|
|
|
|
if (it != browser_registered_function_.cend())
|
|
|
|
|
{
|
|
|
|
|
auto function = it->second;
|
2019-09-20 16:27:58 +08:00
|
|
|
|
nbase::ThreadManager::PostTask(kThreadMain, [=]() {
|
2019-04-19 17:19:57 +08:00
|
|
|
|
function(params, [=](bool has_error, const std::string& json_result) {
|
|
|
|
|
// <20><><EFBFBD>Դ<EFBFBD><D4B4>룬<EFBFBD><EBA3AC>Ҫ<EFBFBD><D2AA>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
args->SetInt(0, js_callback_id);
|
|
|
|
|
args->SetBool(1, has_error);
|
|
|
|
|
args->SetString(2, json_result);
|
|
|
|
|
browser->SendProcessMessage(PID_RENDERER, message);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
args->SetInt(0, js_callback_id);
|
|
|
|
|
args->SetBool(1, true);
|
|
|
|
|
args->SetString(2, R"({"message":"Function does not exist."})");
|
|
|
|
|
browser->SendProcessMessage(PID_RENDERER, message);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|