0x61726b/cef3d

How to implement new handlers

rafadsm opened this issue ยท 16 comments

I really liked your project, I'd like to implement new handlers, such as CefSchemeHandlerFactory, CefResourceHandler, and CefStreamResourceHandler
How could I do this?

Thanks for showing interest in this project!

Currently I'm in the process of evaluating the API design and how I should wrap CEF functionality. I'm trying to make it as close as to Awesomium so Awesomium users can adapt easily. I am working on core design of Cef3D so expect some major changes soon (thats why I havent pushed anything in almost a month). So for now I cant direct you anywhere on how you can go about implementing new things, it will eventually support every basic functionality that CEF has so unfortunately for now you'll have to wait.

I really liked the project and I'm using it in a game, could you tell me how I could implement it myself in the copy of CEF3D?
I tried to follow the OnPaint scheme but I found it very complex because I could not find where the CEF3D gets the CEF data

I wish you good luck with the project because it really is very good, I am using with directx9 without problems

The current implemented handlers are CefDisplayHandler CefLifeSpanHandler etc. You can find it on Cef3DHandler.h. You'll add your handlers here. For further instructions you can check out the example CEF project which implements CefResourceHandler.

Hi again thanks for responding
I've tried adding something simple, RequestDumpResourceProvider
Using CefResourceManager, though, my GetResourceHandler is not receiving data, could I look at the code?
Here are all the things I added in Cef3DHandler.cpp
Here are all the things I added in Cef3DHandler.h

I did the test I did add a MessageBox to know every time a function is returning a value in 'cefclient source' and it worked, but in my code, it does not
I did the same way used in client_handler..h/cc in cefclient source

Hey, I quickly looked at your code and realized you missed this:
CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE { return this; }

Add this to the header and it should totally work. You need to tell CefClient to use this class when its trying to understand which RequestHandler to use.

Another thing, since there is no javascript to C++ bindings yet, if you want to quickly do it yourself you can look through this repository in its old state. I've used this project on my engine a year ago. Here is a video where im demonstrating this. And about 3 months ago I decided to resurrect this project and decouple it from my engine. You can see here for the old state of this project with working javascript to c++ (or the reverse) bindings. The magic happens here and here. Again you dont actually need this, just to give a direction. You can always look at the official CEF sample for ideas.

Thanks again, I got it!
It is the first version of CEF that I used was from its engine, but it did not create the browser, I tried because it was simpler, I also tried several bases on the internet and all gave me the same result, its latest version of cef3d worked Perfectly, change it to multi_thread
At the moment I'm creating pages loaded in file in memory, because the game in which I'm deploying uses an LZMA-based file system
Soon I will add V8Handler, Thanks for helping me

CefResourceManager::AddArchiveProvider would add .zip as a site?
For example:
Resource_manager->AddArchiveProvider ("http://test", "myzip.zip", std :: string (), 100, std :: string ());

Myzip.zip contains a .html file named index.html

If you access the url http://test will display all the contents of myzip.zip (index.html)?

Unfortunately I have no experience with CefResourceManager. The "archive" might be a pak file. I'm not sure

I've noticed that fps in videos and animations does not exceed 30 even framerate setting higher through command line, do you have any idea what it could be?

Oh yeah, since I'm still planning on the API design the CefBrowserSettings object doesnt get set properly. For now, you can go Cef3DUtils.h and find the method Cef3DBrowserDefinitionToCef and add this if condition. I think you can't get more than 60 FPS due to limitations in Chromium

if (Definition.Type == Cef3DBrowserType::Offscreen)
     settings.windowless_frame_rate = 60;

When I do this I can get 60FPS on the Direct3D 11 sample app.

Could you let me know what this is for?
What would be "yume" in CefRegisterExtension?

How could I pass all values received in Cef3DV8Handler::Execute to Cef3D::Cef3DDelegates as Cef3D::Cef3DDelegates::OnPaint.Add(CEF3D_BIND(&Cef3DDelegate::OnPaint,Cef3DListener.get()) ?
Thank you again! ๐Ÿ˜„

Here is an overview of how "extension" works in Cef.

An extension is a global javascript object. When the renderer thread is ready, we pass a javascript object to CefRegisterExtension and tell it to bind the javascript object to yume. You can think of it like this.

Extension string: var plus = function(a,b) { return a + b; }
When you call CefRegisterExtension("yume",extension string, ,v8); what will happen is when the DOM is ready on the HTML side you can call yume.plus(1,2) and it will return 1+2. So what CefRegisterExtension does is bind global javascript objects from C++ side given a string.

We can trace back this javascript extension code. Since V8 is on renderer process, the extension loading should be there too. Here is CefSubProcess sending the extension string from a hardcoded path. You should write your own javascript string here.And here is the js file that it is loading.

What is this for? Now looking at the Cef3D.js , when we call SendDOMEvent like this, it goes to Renderer Process, and the renderer process redirects the message to Browser Process. On the browser process' OnProcessMessageReceived we catch this message ( here ) and do what you want with the values.

I hope this can give a rough idea how to handle bindings from/to c++/javascript. It gave me headaches until I figured it out too.

Thanks, I added the v8, however, I have a small problem with the parameters, Cef3D.log returns the error:
ERROR:Cef3DRenderer.cpp(62)] Function called without callback param: SendDomEvent2

I would like you to look at my code, because I did exactly the same as yours.

Cef3D.js

var Game = Game || {};

Game.SendDomEvent = function() {
  native function SendDomEvent();

  SendDomEvent();
};

Game.SendDomEvent2 = function(str) {
  native function SendDomEvent2();

  SendDomEvent2(str);
};

Page.html

<html>
<head>
</head>
<body>
<button onclick="Game.SendDomEvent()">Game.SendDomEvent</button>
<button onclick="Game.SendDomEvent2('str')">Game.SendDomEvent str</button>
</body>
</html>

Well, if I use the function without parameter, it works
If I send with parameters, it does not work

bool Cef3DV8Handler::Execute

bool Cef3DV8Handler::Execute(
		const CefString &name, CefRefPtr<CefV8Value> object,
		const CefV8ValueList &arguments,
		CefRefPtr<CefV8Value> &retval,
		CefString &exception)
	{

		CefRefPtr<CefBrowser> browser = CefV8Context::GetCurrentContext()->GetBrowser();
		if (!browser)
			return false;

		LOG(INFO) << "Received Js execute";

		auto message = CefProcessMessage::Create(name);
		auto message_args = message->GetArgumentList();

		if (arguments.size() > 0
			&& !arguments[0]->IsFunction()
			&& !arguments[0]->IsNull()
			)
		{
			std::string function_name = name;
			LOG(ERROR) << "Function called without callback param: "
				<< function_name;

			return false;
		}

		if (arguments.size() > 0 && arguments[0]->IsFunction()) {
			// The first argument is the message id
			client_app_->AddCallback(messageId, CefV8Context::GetCurrentContext(), arguments[0]);
			Cef3DHelpers::SetListValue(message_args, 0, CefV8Value::CreateInt(messageId));
		}
		else {
			Cef3DHelpers::SetListValue(message_args, 0, CefV8Value::CreateNull());
		}

		// Pass the rest of the arguments
		for (unsigned int i = 1; i < arguments.size(); i++)
			Cef3DHelpers::SetListValue(message_args, i, arguments[i]);
		browser->SendProcessMessage(PID_BROWSER, message);

		retval = CefV8Value::CreateInt(50);
		messageId++;
		return true;
	}

Could you help me figure out why this error when using parameter?

Can you try <button onclick="Game.SendDomEvent(function() {}, 1234,"1234")">Game.SendDomEvent</button> ?

And

Cef3D.SendDomEvent = function(callback,s,type,v) {
  native function SendDomEvent();

  SendDomEvent(callback,s,type,v);
};

Another tip: if you "Attach to Process" in Visual Studio and pick the cef3d subprocess you can debug V8Handler::Execute function.

I was researching something to make things easier using html and javascript, I found the REACT, and realized that in your engine, you used REACT, this library is made the page using webpack in nodejs and compiling or I can simply create an html file and To include the scripts and use?

Well, since its HTML and stuff, you can do whatever you want. I recommend tutorials like this to get you started on React + webpack. There are tons of tutorials online. You dont have to use any compilers though. React works with vanilla javascript.