mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
ChromiumBrowser: executution of native code from javascript and vice versa
git-svn-id: svn://ultimatepp.org/upp/trunk@8489 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
bbf1d2ac5f
commit
15044fed20
11 changed files with 140 additions and 36 deletions
|
|
@ -30,11 +30,11 @@ public:
|
|||
ChromiumBrowser();
|
||||
~ChromiumBrowser();
|
||||
|
||||
Callback1<String> WhenUrlChange;
|
||||
Callback1<String> WhenMessage;
|
||||
Callback WhenTakeFocus;
|
||||
Callback1<bool> WhenKeyboard;
|
||||
Callback3<Upp::String, int, Upp::String> WhenConsoleMessage;
|
||||
Callback1<String> WhenUrlChange;
|
||||
Callback2<String, WithDeepCopy<Vector<Value> > > WhenMessage;
|
||||
Callback WhenTakeFocus;
|
||||
Callback1<bool> WhenKeyboard;
|
||||
Callback3<Upp::String, int, Upp::String> WhenConsoleMessage;
|
||||
|
||||
static void ChildProcess();
|
||||
static bool IsChildProcess();
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
#include "ClientApp.h"
|
||||
|
||||
|
||||
static const char * const func_names[]={
|
||||
"JSExample1"
|
||||
};
|
||||
|
||||
|
||||
ClientApp::ClientApp()
|
||||
{
|
||||
//Add our own JS functions to the list
|
||||
functions.Add("JSExample1", Upp::callback(this, &ClientApp::JSExample1));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -20,9 +23,9 @@ void ClientApp::OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFra
|
|||
{
|
||||
//Register our JS functions
|
||||
CefRefPtr<CefV8Value> object = context->GetGlobal();
|
||||
for(int f = 0; f < functions.GetCount(); f++){
|
||||
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(~functions.GetKey(f), this);
|
||||
object->SetValue(~functions.GetKey(f), func, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
for(int f = 0; f < __countof(func_names); f++){
|
||||
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(func_names[f], this);
|
||||
object->SetValue(func_names[f], func, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,19 +39,26 @@ void ClientApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser, CefRefPtr<Ce
|
|||
|
||||
bool ClientApp::Execute(const CefString& name, CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval, CefString& exception)
|
||||
{
|
||||
int f = functions.Find(name.ToString());
|
||||
if (f >= 0){
|
||||
functions[f].Execute(arguments, retval, exception);
|
||||
return true;
|
||||
}else{
|
||||
RLOG(Upp::String("ERROR: Unknown native function: ") + name.ToString());
|
||||
}
|
||||
|
||||
return false;
|
||||
CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(name);
|
||||
CefRefPtr<CefListValue> par = message->GetArgumentList();
|
||||
V8ValueListToCefListValue(arguments, par);
|
||||
CefRefPtr<CefBrowser> browser = CefV8Context::GetCurrentContext()->GetBrowser();
|
||||
if (browser) browser->SendProcessMessage(PID_BROWSER, message);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ClientApp::JSExample1(const CefV8ValueList& args, CefRefPtr<CefV8Value>& retval, CefString& exc)
|
||||
void ClientApp::V8ValueListToCefListValue(const CefV8ValueList& src, CefRefPtr<CefListValue> & dst)
|
||||
{
|
||||
retval = CefV8Value::CreateString("Function that returns some string");
|
||||
for (unsigned i = 0; i < src.size(); i++)
|
||||
{
|
||||
if (!src[i]->IsValid()) { dst->SetString(dst->GetSize(),"Invalid V8Value"); continue;}
|
||||
if (src[i]->IsUndefined() || src[i]->IsNull()) { dst->SetNull(dst->GetSize()); continue;}
|
||||
if (src[i]->IsBool()) { dst->SetBool(dst->GetSize(), src[i]->GetBoolValue()); continue;}
|
||||
if (src[i]->IsInt()) { dst->SetInt(dst->GetSize(), src[i]->GetIntValue()); continue;}
|
||||
if (src[i]->IsDouble()) { dst->SetDouble(dst->GetSize(),src[i]->GetDoubleValue()); continue;}
|
||||
if (src[i]->IsString()) { dst->SetString(dst->GetSize(),src[i]->GetStringValue()); continue;}
|
||||
|
||||
dst->SetString(dst->GetSize(), "Unimplemented V8Value conversion");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@ class ClientApp: public CefApp,
|
|||
private:
|
||||
|
||||
CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() { return this; }
|
||||
|
||||
Upp::VectorMap<Upp::String, Upp::Callback3<const CefV8ValueList&, CefRefPtr<CefV8Value>&, CefString&> > functions;
|
||||
void JSExample1(const CefV8ValueList&, CefRefPtr<CefV8Value>&, CefString&);
|
||||
void V8ValueListToCefListValue(const CefV8ValueList& src, CefRefPtr<CefListValue> & dst);
|
||||
|
||||
public:
|
||||
typedef ClientApp CLASSNAME;
|
||||
|
|
|
|||
|
|
@ -66,11 +66,45 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
|
|||
bool ClientHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, CefProcessId source_process, CefRefPtr<CefProcessMessage> message)
|
||||
{
|
||||
if (message->GetName().ToString() == "show_keyboard"){
|
||||
|
||||
PostCallback(callback1(WhenKeyboard, true));
|
||||
|
||||
}else if (message->GetName().ToString() == "hide_keyboard"){
|
||||
|
||||
PostCallback(callback1(WhenKeyboard, false));
|
||||
|
||||
}else{
|
||||
PostCallback(callback1(WhenMessage, message->GetName().ToString()));
|
||||
|
||||
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
||||
Upp::Vector<Upp::Value> par;
|
||||
|
||||
for (unsigned i = 0; i < args->GetSize(); i++){
|
||||
CefValueType type = args->GetType(i);
|
||||
switch(type){
|
||||
|
||||
case VTYPE_BOOL:
|
||||
par.Add(args->GetBool(i));
|
||||
break;
|
||||
|
||||
case VTYPE_DOUBLE:
|
||||
par.Add(args->GetDouble(i));
|
||||
break;
|
||||
|
||||
case VTYPE_INT:
|
||||
par.Add(args->GetInt(i));
|
||||
break;
|
||||
|
||||
case VTYPE_STRING:
|
||||
par.Add(args->GetString(i).ToString().c_str());
|
||||
break;
|
||||
|
||||
default:
|
||||
par.Add("OnProcessMessageReceived: unsupported parameter type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PostCallback(callback2(WhenMessage, message->GetName().ToString(), par));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -87,8 +121,10 @@ void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
|
|||
CefRefPtr<CefContextMenuParams> params,
|
||||
CefRefPtr<CefMenuModel> model)
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
//Empty context menu
|
||||
model->Clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class ClientHandler : public CefClient, public CefLifeSpanHandler, public CefDis
|
|||
|
||||
public:
|
||||
ClientHandler( Upp::Callback1<Upp::String> & wuc,
|
||||
Upp::Callback1<Upp::String> & wm,
|
||||
Upp::Callback2<Upp::String, Upp::WithDeepCopy<Upp::Vector<Upp::Value> > > & wm,
|
||||
Upp::Callback & tf,
|
||||
Upp::Callback1<bool> & wk,
|
||||
Upp::Callback3<Upp::String, int, Upp::String> & wcm):
|
||||
|
|
@ -33,7 +33,7 @@ public:
|
|||
~ClientHandler() { }
|
||||
|
||||
Upp::Callback1<Upp::String> & WhenUrlChange;
|
||||
Upp::Callback1<Upp::String> & WhenMessage;
|
||||
Upp::Callback2<Upp::String, Upp::WithDeepCopy<Upp::Vector<Upp::Value> > > & WhenMessage;
|
||||
Upp::Callback & WhenTakeFocus;
|
||||
Upp::Callback1<bool> & WhenKeyboard;
|
||||
Upp::Callback3<Upp::String, int, Upp::String> & WhenConsoleMessage;
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@ class ChromiumBrowserExample : public WithChromiumBrowserExampleLayout<TopWindow
|
|||
|
||||
private:
|
||||
|
||||
void Close() { Upp::ShowKeyboard(false); TopWindow::Close(); }
|
||||
void OnUrlChange(String url) { Url.SetData(url); Url.CancelSelection(); }
|
||||
void OnTakeFocus() { Url.SetFocus(); }
|
||||
void OnConsoleMessage(String url, int line, String msg) { RLOG(Format("Console message: url=%s, line=%d, msg=%s", url, line, msg)); }
|
||||
void OnBrowse() { Browser.Browse(~Url); }
|
||||
void Close() { Upp::ShowKeyboard(false); TopWindow::Close(); }
|
||||
void OnUrlChange(String url) { Url.SetData(url); Url.CancelSelection(); }
|
||||
void OnTakeFocus() { Url.SetFocus(); }
|
||||
void OnConsoleMessage(String url, int line, String msg) { RLOG(Format("Console message: url=%s, line=%d, msg=%s", url, line, msg)); }
|
||||
void OnBrowse() { Browser.Browse(~Url); }
|
||||
void OnMessage(String name, WithDeepCopy<Vector<Value> > par);
|
||||
void OnJSTests();
|
||||
|
||||
public:
|
||||
typedef ChromiumBrowserExample CLASSNAME;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
LAYOUT(ChromiumBrowserExampleLayout, 388, 260)
|
||||
LAYOUT(ChromiumBrowserExampleLayout, 504, 260)
|
||||
ITEM(Button, Back, Tip(t_("Go back")).LeftPosZ(4, 48).TopPosZ(4, 44))
|
||||
ITEM(Button, Forward, Tip(t_("Go forward")).LeftPosZ(56, 48).TopPosZ(4, 44))
|
||||
ITEM(Button, Refresh, Tip(t_("Refresh current page")).LeftPosZ(108, 48).TopPosZ(4, 44))
|
||||
ITEM(EditString, Url, SetFont(StdFontZ(32)).HSizePosZ(160, 108).TopPosZ(4, 44))
|
||||
ITEM(Button, Go, Tip(t_("Go")).RightPosZ(56, 48).TopPosZ(4, 44))
|
||||
ITEM(Button, Stop, Tip(t_("Stop")).RightPosZ(4, 48).TopPosZ(4, 44))
|
||||
ITEM(EditString, Url, SetFont(StdFontZ(32)).HSizePosZ(160, 160).TopPosZ(4, 44))
|
||||
ITEM(Button, Go, Tip(t_("Go")).RightPosZ(108, 48).TopPosZ(4, 44))
|
||||
ITEM(Button, JSTests, SetLabel(t_("JS Test")).Tip(t_("Stop")).RightPosZ(4, 48).TopPosZ(4, 44))
|
||||
ITEM(ChromiumBrowser, Browser, StartPage("http://ultimatepp.org").HSizePosZ(0, 0).VSizePosZ(52, 0))
|
||||
ITEM(Button, Stop, Tip(t_("Stop")).RightPosZ(56, 48).TopPosZ(4, 44))
|
||||
END_LAYOUT
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ options(GCC) -std=c++11;
|
|||
link(GCC) "-Wl,-rpath .";
|
||||
|
||||
file
|
||||
html/test_page.html,
|
||||
files.brc,
|
||||
Utils readonly separator,
|
||||
Utils.h,
|
||||
Utils.cpp,
|
||||
|
|
|
|||
2
bazaar/ChromiumBrowserExample/files.brc
Normal file
2
bazaar/ChromiumBrowserExample/files.brc
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
BINARY(test_page, "html/test_page.html")
|
||||
|
||||
29
bazaar/ChromiumBrowserExample/html/test_page.html
Normal file
29
bazaar/ChromiumBrowserExample/html/test_page.html
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<style>
|
||||
body {background-color: #EFEFEF}
|
||||
canvas, label, button {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p><label style="font-size:30px" id="some_label">Waiting for some action...</label></p>
|
||||
<p><button style="font-size:30px" onclick="JSExample1('some string', true, 777);">Press me to execute native function from JS!</button></p>
|
||||
|
||||
<script>
|
||||
function CallbackExample(r)
|
||||
{
|
||||
document.getElementById('some_label').innerHTML = 'Javascript function executed by native code: ' + r;
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -6,6 +6,7 @@ using namespace Upp;
|
|||
#define IMAGEFILE <ChromiumBrowserExample/ChromiumBrowserExample.iml>
|
||||
#include <Draw/iml.h>
|
||||
|
||||
#include "files.brc"
|
||||
|
||||
ChromiumBrowserExample::ChromiumBrowserExample()
|
||||
{
|
||||
|
|
@ -23,6 +24,7 @@ ChromiumBrowserExample::ChromiumBrowserExample()
|
|||
Browser.WhenTakeFocus = THISBACK(OnTakeFocus);
|
||||
Browser.WhenKeyboard = STDBACK(::ShowKeyboard);
|
||||
Browser.WhenConsoleMessage = THISBACK(OnConsoleMessage);
|
||||
Browser.WhenMessage = THISBACK(OnMessage);
|
||||
|
||||
Back.WhenAction = callback(&Browser, &ChromiumBrowser::GoBack);
|
||||
Forward.WhenAction = callback(&Browser, &ChromiumBrowser::GoForward);
|
||||
|
|
@ -30,6 +32,7 @@ ChromiumBrowserExample::ChromiumBrowserExample()
|
|||
Url.WhenEnter = THISBACK(OnBrowse);
|
||||
Go.WhenAction = THISBACK(OnBrowse);
|
||||
Stop.WhenAction = callback(&Browser, &ChromiumBrowser::Stop);
|
||||
JSTests.WhenAction = THISBACK(OnJSTests);
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
Maximize();
|
||||
|
|
@ -40,6 +43,27 @@ ChromiumBrowserExample::ChromiumBrowserExample()
|
|||
}
|
||||
|
||||
|
||||
|
||||
void ChromiumBrowserExample::OnJSTests()
|
||||
{
|
||||
Browser.ShowHTML(String(test_page, test_page_length));
|
||||
}
|
||||
|
||||
|
||||
void ChromiumBrowserExample::OnMessage(String name, WithDeepCopy<Vector<Value> > par)
|
||||
{
|
||||
String tmp = "Native function executed by JS:&[* " + name + "(";
|
||||
for (int i = 0; i < par.GetCount(); i++){
|
||||
if (i > 0) tmp += ',';
|
||||
tmp += DeQtfLf(par[i].ToString());
|
||||
}
|
||||
tmp += ") ]&&After you press OK javascript function will be executed by native code";
|
||||
PromptOK(tmp);
|
||||
|
||||
Browser.ExecuteJavaScript(Format("CallbackExample(%d);", (int)Random()));
|
||||
}
|
||||
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
StdLogSetup(LOG_FILE | LOG_CERR | LOG_TIMESTAMP | LOG_APPEND);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue