-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Javascript Binding v2 #2246
Comments
…CefSharpSettings.LegacyJavascriptBindingEnabled = true See cefsharp#2246 for details
…CefSharpSettings.LegacyJavascriptBindingEnabled = true See cefsharp#2246 for details
* JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See #2246 for details
* JSB Rewrite - Add CefSharp.RegisterBoundObject javascript method To get around the problem of IPC timing, I've reversed the communication, now it's the render process requesting the bound objects, the implementation is incomplete at this stage, more just a basic proof of concept Rewrite BindingTest.html using QUnit One of the tests doesn't map correctly as it requires def user interaction TODO: - Get objects by name - Rename Messages.h values that relate to this change so they are more descriptive - Better error handling - Caching of objects within a render process - Investigate global context options, don't think it's possible to call an async method directly in the global context # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB Improve Request/Response message names * BindingTest.html - Output stress test results * Remove JavascriptRootObject was leftover from time we used WCF to transmit objects * JavascriptObjectRepository - Objects are now sent in the same list with an IsAsync flag Separation when sending over IPC with two unique lists isn't necessary * JavascriptObjectRepository - Return objects by name or return all by default Untabify CefAppUnmanagedWrapper.cpp Add minor comment to CefBrowserWrapper for a reminder that we use Frame Identifier as dictionary key * Add //TODO: JSB comments for work that's left to be done Ideally within a render process we cache bound objects once they've been communicated, It would also be nice to make multiple binding requests so objects can later be added dynamically * JSB Allow multiple calls to CefSharp.RegisterBoundObject Update BindingTest.html to name two distinct calls to different bound objects * JSB - Add some notes about caching, no working implementation yet * JSB - Dynamically Register object on Request * JSB Add ability to unbind an object and rename RegisterBoundObject to BindObjectAsync # Conflicts: # CefSharp.Example/Resources/BindingTest.html * JSB BindObjectAsync - if objects already bound then return false * JSB - Ignore Indexer properties Were previously throwing an exception * JSB - Add LegacyJavascriptBindingEnabled option so preserve existing behaviour This is only useful for SPA application and those that only navigate to pages hosting within a single domain. Any sort of cross-site navigation and a new render process will be spawned and objects won't be bound automatically (You can use the new methods to request they're bound yourself, at least in theory, more testing required on this) * Add LegacyBindingTest.html Current disabled by default. To enable uncomment CefSharpSettings.LegacyJavascriptBindingEnabled = true; in CefExample.cs * RegisterJsObject and RegisterAsyncJsObject can now only be used when CefSharpSettings.LegacyJavascriptBindingEnabled = true See #2246 for details
|
I'm doing However the method is getting null data. The paramters passed in the js call are null. If I use |
@Example111 Can you provide a mode detail example? Are you upgrading an existing app or developing a new one?
If you set |
Hi @amaitland sorry I wasn't clear. This is an existing app and was working fine with cross site and the old way to register. Register: C# function:
JS: It works but our data parameter is always null. Instead of having the values passed from js |
@Example111 Thanks for the more detailed example 👍 There was a minor breaking change to add support for public void f(Dictionary<string, object> data = null) to public void f(IDictionary<string, object> data = null) Basically use the interface instead of the implementation and hopefully it'll start working again. Will need to amend the documentation to alert people of the subtle change. Or alternatively use the public void f(dynamic data = null) |
We use CEF on Mac and CefSharp on Windows. With the new CefSharp binding implementation, would we need to use Javascript logic like |
@chris-araman You'd be the most qualified to answer your own questions as I've got no idea what your requirements are. Can you use the legacy mode? How many browser instances are you using at any one time? If only one then you can limit the number of render processes. |
Fixed a bug where
|
The The |
|
What would it take to write a |
Issue #2273 has been reported and will be fixed when I'm in front of an actual computer, might be a few days or more. @jsoldi It would be possible to add a function that returns a promise that resolves to an object without adding it to the context, I had considered this. Promises are required as all communication is done using CEF/Chromium IPC. |
For clarity it would be possible to do that if the object has already been cached within a render process, in could in theory be used in conjunction with |
The |
The new binding methodology will not work unless:
Is this intended? The way I am registering is like so:
|
You must call 'CefSharp.BindObjectAsync' in JavaScript to register an object, see my original post for examples. The behavior of legacy binding is working as expected. |
Ok, I see now, the extra step of calling |
No problem. I'll update the original post with some more details when I'm in front of a computer. Try make it clearer |
Hello! And sorry for my bad english. public MainWindow() {
InitializeComponent();
Browser.JavascriptObjectRepository.Register("boundAsync", new BoundObject(), true);
Browser.FrameLoadEnd += (sender, args) => {
IFrame frame = args.Frame;
if (frame.IsMain) {
frame.ExecuteJavaScriptAsync(File.ReadAllText("script.js"));
}
};
} script.js looks like: (async function(){
await CefSharp.BindObjectAsync("boundAsync");
})();
// do something usefull
boundAsync.callSomeMethod();
window.location.href = "/*href*/"; I'v also tried to unbind object and set it undefined in javascript before redirection: CefSharp.DeleteBoundObject("boundAsync");
window.boundAsync === undefined; But it also didn't work. Memory usage continues to increase with every redirect. I would be very grateful for any kind of help. |
@CoolPixEll Please fork https://github.com/cefsharp/CefSharp.MinimalExample and provide a working example that reproduces your problem. Then push the changes to GitHub, no zip files thank you. |
I'm having a terrible time with the new object binding - I can get trivial binding to work using built-in types, but as soon as I have a method that returns an object, the promise just dies. I have forked the minimal example, and created a very simple example where an object is bound. This object contains two methods, one returning a simple string and one returning a child object:
I can bind OK to the top-level object, but calls to the method that returns the ChildBoundObject doesn't work. I attempted an alternative approach, which was to register the ChildBoundObject also within the You can see the fork here: https://github.com/lewk2/CefSharp.MinimalExample Having a totally flat object heirarchy is a real pain for me, since I want to walk down an object graph and still be able to access methods as I go. It cannot be that what I'm doing is unsupported - it has to be a bug (I hope, otherwise I must return to IE11 land with the WebBrowser control - not a happy thought!) |
@lewk2 Thanks for the reproducible example, it is indeed a bug. Short term you can return a struct or an array of classes, it's only returning a single class that's broken. https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/AsyncBoundObject.cs#L41 Objects are cached within the render process, deleting an object does not currently remove the object from the meta data cache, I will look to see what's involved in adding a second removeFromCache param. |
OK, I did a little more polishing of the test fork (which was actually missing a final git push, because I managed to miss the prompt for my password before leaving for home!). I can confirm I can get an array of objects returned from a method - but they seem to come back looking more like a flat rendering of the properties of that class. I no longer have any callable methods, and now have accessible properties (which in full async mode should not exist). I extended the fork to show the general broken case, and also the flattening effect. I would also like to float the idea that perhaps having even basic type properties (string, int, bool) being able accessible without using promises would be a nice feature. It causes quite a lot of bloat in javascript to access lots of string fields with endless .then calls otherwise... Regarding the object cache - my plan is to mount just a single proxy bridge class, and work from there. I only started to insert multiple objects as a work-around to my above problems. I could imagine people being blocked in the future if there is no way to remove / replace an object though through the lifecycle of the app... so having a true 'delete' (either in JavaScript or C#) is probably needed. I now have a difficult choice - we have a project that needs to create a plugin architecture, and I must decide if we fall back to IE11 embedded (which is a total dead-end), move back to CEF legacy binding (which means API / object model we build now within plugins will probably break when we move forward) or to help get the modern bindings working well. I'm happy to put some effort into 'getting the new stuff working' - but if this is going to take weeks, i need to pick another path... Anything I can do to get testing or dev effort applied to improving this, I'm happy to pitch in. |
Previous versions only supported returning
That's not possible with the As for the
|
The Includes the bug fix for returning a class using |
The |
Additional note for those using There is the potential for this to be a problem with the newer implementation as well, should only be an issue if you bind a different object type using the same key. e.g. browser one has object of type See RequestContext for more details |
Seems that CefSharp.DeleteBoundObject(name) doesn't also perform the action of CefSharp.RemoveObjectFromCache(name). Basically trying to replace a binding like this doesn't work: Adding a call to CefSharp.RemoveObjectFromCache() before DeleteBoundObject() seems to fix the issue, but is unintuitive in my opinion. |
getting error in javacript code Uncaught ReferenceError: CefSharp is not defined...i am not finding any .js file after adding cefsharp to my .net project in vs |
Due to
Chromium
changes the currentJSB
implementation no longer works as it previously did, bound objects are no longer available aftercross-site
navigation. For details on that see #1203 for historic details.With the
63.0.0
release changes have been made to revamp the way objects are bound. There will be two options, the legacy behaviour which will still work forSingle Page Applications
and where only a single domain is used. The new features which will have quite a few advantages.Legacy Binding
You will need to set
CefSharpSettings.LegacyJavascriptBindingEnabled = true
before you register your first object (both methodsRegisterJsObject
andRegisterAsyncJsObject
).If you perform
cross-site
navigation's you will no longer be able to use this method to bind objects. If you only use a singleChromiumWebBrowser
instance in your application then it's possible to limit the number of render processes using therenderer-process-limit=1
command line flag. See https://github.com/cefsharp/CefSharp/blob/cefsharp/63/CefSharp.Example/CefExample.cs#L61 for an example.New Binding Method
The new binding method has many advantages
Binding is now initiated by JavaScript, the
CefSharp.BindObjectAsync
method returns aPromise
that is resolved when the objects are available. Objects are created in the global context (window
, the same as the previous behaviour). If you callCefSharp.BindObjectAsync
without any params then all registered objects will be bound. Binding by name is the more descriptive options.You have two options for registering an object in
.Net
, the first is similar to the old behaviour where an object is registered in advance. The second options is more flexible and allows objects to beResolved
when required.To be notified in
.Net
when objects have been bound inJavaScript
then you can subscribe to the ObjectBoundInJavascript eventFor reference the set of
QUnit
test cases used are https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Example/Resources/BindingTest.htmlThe text was updated successfully, but these errors were encountered: