Skip to content

Conversation

@Geevo
Copy link
Contributor

@Geevo Geevo commented May 14, 2020

Fixes: [#2831]

Summary:
I have added a new feature to the Javascript Binding implementation that gives the ability to configure custom property names for both normal and camelCase binding objects.

I've never written in C++ before so lots of reading in and around the wrapper to grasp an idea of how i would implement this so apologies in advanced if i have missed something with regards to anything unmanaged related, and of course i'm happy to try and change or refactor anything you're not happy with.

I've tried to make sure this doesn't cause anything breaking changes and default values are used if the properties are never configured.

Changes:

  • Created two new properties in the CefSharpSettings and assigned them default values
  • Changes made to the ManagedCefBrowserAdapter to retrieve the properties from CefSharpSettings
  • Created a new StringCheck class/file (cs Internals) to validate the strings do not contain illegal characters
  • Changes to the CefAppUnmanagedWrapper to receive the new properties via the extraInfo parameter on OnBrowserCreated

How Has This Been Tested?
Obviously this is a tad bit trickier to test. I had to make changes to all the html code to reflect the new values i was testing with (changes not included in this PR).

Using WinForms Example for testing, i set custom values to the new properties CefSharpSettings.JavascriptBindingPropertyName and CefSharpSettings.JavascriptBindingPropertyNameCamelCase and run the Binding Test accordingly and didn't receive any errors.

I tested with illegal characters to ensure an exception was thrown with an explanation as to why the exception was thrown.

I tested with VS 2019 Professional on Windows 10 (1809)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Updated documentation

Checklist:

  • Tested the code(if applicable)
  • Commented my code
  • Changed the documentation(if applicable)
  • New files have a license disclaimer
  • The formatting is consistent with the project (project supports .editorconfig)

@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

@amaitland amaitland changed the title Feature - Configure custom JavaScript binding property names. Feature - Configure property name that Cefsharp injects to window May 14, 2020
@amaitland
Copy link
Member

Obviously this is a tad bit trickier to test. I had to make changes to all the html code to reflect the new values i was testing with (changes not included in this PR).

I think this is an argument against adding properties to CefSharpSettings, these should probably be per browser. Having LegacyJavascriptBindingEnabled and WcfEnabled as global was a mistake and once we come up with a per browser place to put these settings those should be migrated as well.

I'm not sure exactly where they should go, possible a settings object should be added to the JavascriptObjectRepository.

Further comments inline.

///
/// NOTE: There are two properties to be mindful of, this and <see cref="JavascriptBindingPropertyNameCamelCase"/>
/// </summary>
public static string JavascriptBindingPropertyName { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • We we need two properties for this? Camel case can be derived from the full name
  • What happens if both properties are exactly the same?

If they both end up being the same name we should only generate one set of objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about exposing a single property and then manipulate the string to pascal/camel case on the first char of the property before injecting that way you can keep both objects and cater for either preference?

For example:
https://stackoverflow.com/a/36579722

Or simply leave it down to preference completely, and only have a single object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single property sounds fine, if the first character is already lower we should only create one set of objects.

https://github.com/cefsharp/CefSharp/blob/master/CefSharp/Internals/JavascriptObjectRepository.cs#L543 should be refactored if we add an additional method for camel case conversion.

@AppVeyorBot
Copy link

Add new property to JavascriptObjectRepository.
Added IsFirstCharacterLowercase to StringCheck class
Changed ManagedCefBrowserAdapter to retrieve property from JavascriptObjectRepository.
Added if statement if property is already camelCase.
@AppVeyorBot
Copy link

@Geevo
Copy link
Contributor Author

Geevo commented May 18, 2020

I think it maybe worth having a method to set the WindowPropertyName. That way you check if the browser is initialised beforehand, otherwise it could be too late and injected property name will remain the default configuration.

Maybe also perhaps then have get only property with the last known set name.
And throw an exception when trying to set when the browser is already initialised?

@AppVeyorBot
Copy link

@AppVeyorBot
Copy link

amaitland added a commit to amaitland/CefSharp that referenced this pull request May 19, 2020
- Rename settings object to JavascriptBindingSettings
- Validate JavascriptBindingSettings.JsBindingPropertyName in setter to provide immediate
  feedback
- Add FreezableBase which throws exception when frozen (we can reuse this for some other settings classes)

TODO:
- Xml doc fill in the blanks
- Add unit tests

Follow on from cefsharp#3126
amaitland added a commit to amaitland/CefSharp that referenced this pull request May 23, 2020
- Rename settings object to JavascriptBindingSettings
- Validate JavascriptBindingSettings.JsBindingPropertyName in setter to provide immediate
  feedback
- Add FreezableBase which throws exception when frozen (we can reuse this for some other settings classes)

TODO:
- Xml doc fill in the blanks
- Add unit tests

Follow on from cefsharp#3126
@amaitland
Copy link
Member

I've implemented #2977 which is the reason you'll see conflicting changes in this.

  • Went with a slightly different name in JavascriptBindingSettings as opposed to JavascriptObjectRepositorySettings (I'm still not sure which name I like best, we can change this any time up until this is included in a release branch).
  • Used a Freezable implementation to throw exception of property modified after browser is created.

See a70abc4 for relevant commit.

I've squashed your changes and they're included in the https://github.com/amaitland/CefSharp/commits/feature/jsbpropertyname branch with some additional changes

  • Validate the name in the property setter to provide immediate feedback. This will provide for a clearer call stack in the exception.
  • JsBindingPropertyName is the name I chose, though I'm not convinced that's great either. I think we still need a better name. Really it's the name of the object that's created in the global javascript scope. Open to suggestions on this one.
  • If JsBindingPropertyName is empty then we'll use the current behaviour as default.

Still need to fill in all the xml doc blanks and add some unit tests.

I'll finish the rest when I find some time.

@Geevo
Copy link
Contributor Author

Geevo commented May 28, 2020

  • JsBindingPropertyName is the name I chose, though I'm not convinced that's great either. I think we still need a better name. Really it's the name of the object that's created in the global javascript scope. Open to suggestions on this one.

Perhaps JsBindingGlobalObjectName would better represent the definition of its usage.

As per your description above and definition of the window object described here:
(https://developer.mozilla.org/en-US/docs/Glossary/Global_object)

The window object is the Global Object in the Browser.

Nice touch of the Freezable base implementation 👍

@amaitland
Copy link
Member

Perhaps JsBindingGlobalObjectName would better represent the definition of its usage.

Much better, thanks 👍

Nice touch of the Freezable base implementation

Borrowing the idea from WPF 😄 A few other places we should be able to make use of the base class.

amaitland added a commit to amaitland/CefSharp that referenced this pull request May 29, 2020
- Rename settings object to JavascriptBindingSettings
- Validate JavascriptBindingSettings.JsBindingGlobalObjectName in setter to provide immediate
  feedback
- Add FreezableBase which throws exception when frozen (we can reuse this for some other settings classes)

TODO:
- Add unit tests

Follow on from cefsharp#3126
amaitland added a commit to amaitland/CefSharp that referenced this pull request May 30, 2020
- Rename settings object to JavascriptBindingSettings
- Validate JavascriptBindingSettings.JsBindingGlobalObjectName in setter to provide immediate
  feedback
- Add FreezableBase which throws exception when frozen (we can reuse this for some other settings classes)
- Add some basic Unit Tests (More would be better)

Follow on from cefsharp#3126
amaitland added a commit to amaitland/CefSharp that referenced this pull request May 30, 2020
- Rename settings object to JavascriptBindingSettings
- Validate JavascriptBindingSettings.JsBindingGlobalObjectName in setter to provide immediate
  feedback
- Add FreezableBase which throws exception when frozen (we can reuse this for some other settings classes)
- Add some basic Unit Tests (More would be better)

Follow on from cefsharp#3126
amaitland added a commit that referenced this pull request May 30, 2020
- Rename settings object to JavascriptBindingSettings
- Validate JavascriptBindingSettings.JsBindingGlobalObjectName in setter to provide immediate
  feedback
- Add FreezableBase which throws exception when frozen (we can reuse this for some other settings classes)
- Add some basic Unit Tests (More would be better)

Follow on from #3126
@amaitland
Copy link
Member

Manually merged in 6669110 with additional changes in ae41e10

I ended up with the property named as JavascriptBindingApiGlobalObjectName , it's long I know, hopefully it's at least semi meaningful. Example below.

var settings = browser.JavascriptObjectRepository.Settings;
settings.JavascriptBindingApiGlobalObjectName = "customApi";

I've only got a single very basic test so far ae41e10#diff-59940d85e6a445f319b6a2b0a08bdf9cR77

If anyone has problems then please provide a test case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request - Change property name that Cefsharp injects to window

3 participants