diff --git a/CMakeLists.txt b/CMakeLists.txt
index d40424d..f61c165 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,7 +8,7 @@ if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES "Release")
endif()
-set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY ON)
@@ -473,4 +473,4 @@ if( USE_SPOTIFY_CEF )
install( FILES ${CEF_RESOURCE_DIR}/${resFile} DESTINATION resources)
endif()
endforeach()
-endif()
\ No newline at end of file
+endif()
diff --git a/autobuild.xml b/autobuild.xml
index 6ca9dae..ed3aee1 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -19,11 +19,11 @@
archive
name
darwin64
@@ -33,18 +33,18 @@
archive
name
windows64
version
- 139.0.17_g6c347eb_chromium-139.0.7258.31
+ cef_bin-148.0.9_g0d9d52a_chromium-148.0.7778.180
package_description
diff --git a/examples/opengl-example/src/opengl-example.cpp b/examples/opengl-example/src/opengl-example.cpp
index f024f10..cfac92a 100644
--- a/examples/opengl-example/src/opengl-example.cpp
+++ b/examples/opengl-example/src/opengl-example.cpp
@@ -79,6 +79,24 @@ void openglExample::handleKeyEvent(int key, int scancode, int action, int mods)
{
mDullahan->requestExit();
}
+ else if (mods & GLFW_MOD_CONTROL)
+ {
+ if (key >= '1' && key <= '9')
+ {
+ std::ostringstream cmd("fromCPP", std::ios::ate);
+ cmd << "(";
+ cmd << "{ ";
+ cmd << "name: 'Key-" + std::to_string(key - '0') << "'";
+ cmd << ", ";
+ cmd << "id: '" + std::to_string(key - '0') << "'";
+ cmd << ", ";
+ cmd << "content : 'Payload for key " + std::to_string(key - '0') << "'";
+ cmd << " }";
+ cmd << ");";
+ std::cout << "--> cmd.str(): " << cmd.str() << std::endl;
+ mDullahan->executeJavaScript(cmd.str());
+ }
+ }
}
}
@@ -311,7 +329,8 @@ bool openglExample::init()
mDullahan->setOnPageChangedCallback(std::bind(&openglExample::onPageChanged, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5));
mDullahan->setOnRequestExitCallback(std::bind(&openglExample::onRequestExitCallback, this));
-
+ mDullahan->setOnJStoCPPMsgCallback(std::bind(&openglExample::onJStoCPPMsgCallback, this, std::placeholders::_1, std::placeholders::_2));
+
mDullahan->navigate(mHomeUrl);
}
@@ -463,6 +482,12 @@ void openglExample::onRequestExitCallback()
glfwSetWindowShouldClose(mWindow, GLFW_TRUE);
}
+std::string openglExample::onJStoCPPMsgCallback(const std::string id, const std::string msg)
+{
+ std::cout << "Received message with ID: " << id << " from JavaScript: " << msg << std::endl;
+ return "Message received loud and clear by C++!";
+}
+
void openglExample::initUI()
{
IMGUI_CHECKVERSION();
@@ -624,7 +649,8 @@ void openglExample::updateUI()
"chrome://version",
"https://sl-viewer-media-system.s3.amazonaws.com/bookmarks/index.html",
"https://viewer-login.agni.lindenlab.com/",
- "https://secondlife.com"
+ "https://secondlife.com",
+ "https://sl-viewer-media-system.s3.amazonaws.com/apps/v8-msg/index.html",
};
static const char* current_item = "Select a bookmark";
ImGui::SetNextItemWidth(main_viewport->Size.x);
diff --git a/examples/opengl-example/src/opengl-example.h b/examples/opengl-example/src/opengl-example.h
index cb85f0c..d234f07 100644
--- a/examples/opengl-example/src/opengl-example.h
+++ b/examples/opengl-example/src/opengl-example.h
@@ -69,6 +69,7 @@ class openglExample
// callbacks
void onPageChanged(const unsigned char* pixels, int x, int y, const int width, const int height);
void onRequestExitCallback();
+ std::string onJStoCPPMsgCallback(const std::string id, const std::string msg);
private:
GLFWwindow* mWindow;
diff --git a/src/dullahan.cpp b/src/dullahan.cpp
index afc0cce..5b9dbe4 100644
--- a/src/dullahan.cpp
+++ b/src/dullahan.cpp
@@ -446,3 +446,8 @@ void dullahan::setOnJSBeforeUnloadCallback(std::function callback)
{
mImpl->getCallbackManager()->setOnJSBeforeUnloadCallback(callback);
}
+
+void dullahan::setOnJStoCPPMsgCallback(std::function callback)
+{
+ mImpl->getCallbackManager()->setOnJStoCPPMsgCallback(callback);
+}
diff --git a/src/dullahan.h b/src/dullahan.h
index 04eee29..06911e5 100644
--- a/src/dullahan.h
+++ b/src/dullahan.h
@@ -397,6 +397,9 @@ class dullahan
// JS before unload callback (alert)
void setOnJSBeforeUnloadCallback(std::function callback);
+ // Message from JS to CPP
+ void setOnJStoCPPMsgCallback(std::function callback);
+
private:
std::unique_ptr mImpl;
};
diff --git a/src/dullahan_browser_client.cpp b/src/dullahan_browser_client.cpp
index f043eee..f3054e6 100644
--- a/src/dullahan_browser_client.cpp
+++ b/src/dullahan_browser_client.cpp
@@ -37,6 +37,7 @@
#include
#include
+#include
#include
dullahan_browser_client::dullahan_browser_client(dullahan_impl* parent,
@@ -58,6 +59,30 @@ CefRefPtr dullahan_browser_client::GetRenderHandler()
return mRenderHandler;
}
+// CefClient override
+bool dullahan_browser_client::OnProcessMessageReceived(CefRefPtr browser,
+ CefRefPtr frame,
+ CefProcessId source_process,
+ CefRefPtr message)
+{
+ CEF_REQUIRE_UI_THREAD();
+
+ if (message->GetName() == "JSONtoCPP_MSG")
+ {
+ CefRefPtr args = message->GetArgumentList();
+ if (args)
+ {
+ //std::cout << ">>> Received JSONtoCPP_MSG from render process: " << args->GetString(0).ToString() << std::endl;
+ mParent->getCallbackManager()->onJStoCPPMsgCallback(args->GetString(0).ToString(), args->GetString(1).ToString());
+ }
+
+ // Indicate we processed this message and it should not be sent to other handlers
+ return true;
+ }
+
+ return false;
+}
+
// CefLifeSpanHandler override
bool dullahan_browser_client::OnBeforePopup(CefRefPtr browser,
CefRefPtr frame,
diff --git a/src/dullahan_browser_client.h b/src/dullahan_browser_client.h
index a6807b2..64e97a2 100644
--- a/src/dullahan_browser_client.h
+++ b/src/dullahan_browser_client.h
@@ -58,6 +58,11 @@ class dullahan_browser_client :
return this;
}
+ bool OnProcessMessageReceived(CefRefPtr browser,
+ CefRefPtr frame,
+ CefProcessId source_process,
+ CefRefPtr message) override;
+
bool OnBeforePopup(CefRefPtr browser,
CefRefPtr frame,
int popup_id,
diff --git a/src/dullahan_callback_manager.cpp b/src/dullahan_callback_manager.cpp
index 715c3c9..d350fad 100644
--- a/src/dullahan_callback_manager.cpp
+++ b/src/dullahan_callback_manager.cpp
@@ -292,3 +292,18 @@ bool dullahan_callback_manager::onJSBeforeUnloadCallback()
return false;
}
+void dullahan_callback_manager::setOnJStoCPPMsgCallback(
+ std::function callback)
+{
+ mOnJStoCPPMsgCallbackFunc = callback;
+}
+
+std::string dullahan_callback_manager::onJStoCPPMsgCallback(const std::string id, const std::string msg)
+{
+ if (mOnJStoCPPMsgCallbackFunc)
+ {
+ return mOnJStoCPPMsgCallbackFunc(id, msg);
+ }
+
+ return std::string();
+}
diff --git a/src/dullahan_callback_manager.h b/src/dullahan_callback_manager.h
index 8141f0e..86a098f 100644
--- a/src/dullahan_callback_manager.h
+++ b/src/dullahan_callback_manager.h
@@ -91,6 +91,9 @@ class dullahan_callback_manager
void setOnJSBeforeUnloadCallback(std::function callback);
bool onJSBeforeUnloadCallback();
+ void setOnJStoCPPMsgCallback(std::function callback);
+ std::string onJStoCPPMsgCallback(const std::string id, const std::string msg);
+
private:
std::function mOnAddressChangeCallbackFunc;
std::function mOnConsoleMessageCallbackFunc;
@@ -111,6 +114,7 @@ class dullahan_callback_manager
std::function(dullahan::EFileDialogType, const std::string, const std::string, const std::string, bool&)> mOnFileDialogCallbackFunc;
std::function mOnJSDialogCallbackFunc;
std::function mOnJSBeforeUnloadCallbackFunc;
+ std::function mOnJStoCPPMsgCallbackFunc;
};
#endif //_DULLAHAN_CALLBACK_MANAGER
diff --git a/src/dullahan_version.h.in b/src/dullahan_version.h.in
index e42c6fd..7f5bf62 100644
--- a/src/dullahan_version.h.in
+++ b/src/dullahan_version.h.in
@@ -37,7 +37,7 @@
// version of this package
#define DULLAHAN_VERSION_MAJOR 1
-#define DULLAHAN_VERSION_MINOR 26
+#define DULLAHAN_VERSION_MINOR 35
#define DULLAHAN_VERSION_POINT 0
// The build version number as of v1.2 is now the date/time the build was made
diff --git a/src/host/dullahan_host.cpp b/src/host/dullahan_host.cpp
index 4d10a64..56bbaf8 100644
--- a/src/host/dullahan_host.cpp
+++ b/src/host/dullahan_host.cpp
@@ -28,6 +28,94 @@
#include "cef_app.h"
+// Shared by Windows and Mac sub-process entry points
+class JSONtoCPPHandler : public CefV8Handler
+{
+ public:
+ JSONtoCPPHandler(CefRefPtr browser) :
+ // Save the browser reference from OnContextCreated()
+ // for later use in IPC communication
+ mBrowser(browser)
+ {
+ }
+
+ bool Execute(const CefString& name,
+ CefRefPtr object,
+ const CefV8ValueList& arguments,
+ CefRefPtr& retval,
+ CefString& exception) override
+ {
+ if (name == "JSONtoCPP")
+ {
+ // Check args
+ if (arguments.size() != 2 || ! arguments[0]->IsString() || ! arguments[1]->IsString())
+ {
+ exception = "JSONtoCPP(json, id) expects two string arguments";
+ return true;
+ }
+
+ // Send the JSON string to the browser process and return an acknowledgment
+ std::string id = arguments[0]->GetStringValue();
+ std::string json = arguments[1]->GetStringValue();
+ std::string result = DoJSONtoCPP(id, json);
+ retval = CefV8Value::CreateString(result);
+
+ // Indicate we handled the function call, even
+ // if there was an error in DoJSONtoCPP
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ std::string DoJSONtoCPP(const std::string& id, const std::string& json)
+ {
+ // Send the JSON string to the browser process via IPC
+ CefRefPtr msg = CefProcessMessage::Create("JSONtoCPP_MSG");
+ CefRefPtr args = msg->GetArgumentList();
+ args->SetString(0, id);
+ args->SetString(1, json);
+ mBrowser->GetMainFrame()->SendProcessMessage(PID_BROWSER, msg);
+
+ // Acknowledge receipt of the JSON string
+ return "{\"ACK\": true}";
+ }
+
+ CefRefPtr mBrowser;
+ IMPLEMENT_REFCOUNTING(JSONtoCPPHandler);
+};
+
+class MyApp : public CefApp,
+ public CefRenderProcessHandler
+{
+public:
+ CefRefPtr GetRenderProcessHandler() override
+ {
+ return this;
+ }
+
+ void OnContextCreated(CefRefPtr browser,
+ CefRefPtr frame,
+ CefRefPtr context) override
+ {
+ CefRefPtr global = context->GetGlobal();
+ CefRefPtr handler = new JSONtoCPPHandler(browser);
+ CefRefPtr func = CefV8Value::CreateFunction("JSONtoCPP", handler);
+ global->SetValue("JSONtoCPP", func, V8_PROPERTY_ATTRIBUTE_NONE);
+
+ // Friendly greeting to the browser process to confirm the context was created
+ CefRefPtr msg = CefProcessMessage::Create("JSONtoCPP_MSG");
+ CefRefPtr args = msg->GetArgumentList();
+ args->SetString(0, "INFO");
+ args->SetString(1, "Hello from the OnContextCreated in the sub-process!");
+ browser->GetMainFrame()->SendProcessMessage(PID_BROWSER, msg);
+ }
+
+private:
+ IMPLEMENT_REFCOUNTING(MyApp);
+};
+
#ifdef __linux__
#if defined(NO_STACK_PROTECTOR)
NO_STACK_PROTECTOR
@@ -49,57 +137,6 @@ int main(int argc, char* argv[])
#include
#include
-/*
- Nasty hack to stop flash from displaying a popup with "NO SANDBOX"
- Flashplayer will try to spawn a cmd.exe and echo this message into it, we
- use a process group to limit the number of processes allowed to 1, thus preventing
- popup.
-
- Limitation: NeedsWindows 8 or higher, the viewer already does put SLPlugin (and with that
- all sub processes) into a job, so all plugin instances get killed when the viewer does exit.
- Anything before Windows 8 will not allow a process being part of more than one job.
-
- Using the sandbox would fix this problem, but for using the sandbox the same executable
- must be used for browser and all sub processes (see cef_sandbox_win.h); but the viewer
- uses slplugin.exe and llceflib_host.exe.
-*/
-void enablePPAPIFlashHack(LPSTR lpCmdLine)
-{
- if (!lpCmdLine)
- {
- return;
- }
-
- std::string strCmdLine = lpCmdLine;
-
- std::string strType = "--type=ppapi";
- std::string::size_type i = strCmdLine.find(strType);
-
- if (i == std::string::npos)
- {
- return;
- }
-
- HANDLE hJob = CreateJobObject(nullptr, nullptr);
- HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ::GetCurrentProcessId());
-
- if (!AssignProcessToJobObject(hJob, hProc))
- {
- ::CloseHandle(hProc);
- ::CloseHandle(hJob);
- return;
- }
-
- JOBOBJECT_BASIC_LIMIT_INFORMATION baseLimits = {};
- baseLimits.LimitFlags = JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
- baseLimits.ActiveProcessLimit = 1;
-
- SetInformationJobObject(hJob, JobObjectBasicLimitInformation, &baseLimits, sizeof(baseLimits));
-
- ::CloseHandle(hProc);
- ::CloseHandle(hJob);
-}
-
// taken from http://magpcss.org/ceforum/viewtopic.php?f=6&t=15817&start=10#p37820
// works around a CEF issue (yet to be filed) where the host process is not destroyed
// after CEF exits in some case on Windows 7
@@ -131,6 +168,7 @@ HANDLE GetParentProcess()
}
#endif
+
#if defined(NO_STACK_PROTECTOR)
NO_STACK_PROTECTOR
#endif
@@ -149,9 +187,11 @@ int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
CefMainArgs args(GetModuleHandle(nullptr));
- enablePPAPIFlashHack(lpCmdLine);
+ // Important: Create the CefApp instance in the main function to ensure it is available
+ // to CefExecuteProcess() when the sub-process is launched. Creating the CefApp instance
+ const CefRefPtr app = new MyApp();
- return CefExecuteProcess(args, nullptr, nullptr);
+ return CefExecuteProcess(args, app, nullptr);
}
#endif
@@ -174,7 +214,10 @@ int main(int argc, char* argv[])
// Provide CEF with command-line arguments.
CefMainArgs args(argc, argv);
+ // Important: same as Windows, CefApp instance should be created in the main function
+ const CefRefPtr app = new MyApp();
+
// Execute the sub-process.
- return CefExecuteProcess(args, nullptr, nullptr);
+ return CefExecuteProcess(args, app, nullptr);
}
#endif