-
-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[dotnet] Implement third-party Permissions module #16414
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
base: trunk
Are you sure you want to change the base?
[dotnet] Implement third-party Permissions module #16414
Conversation
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
Compliance status legend🟢 - Fully Compliant🟡 - Partial Compliant 🔴 - Not Compliant ⚪ - Requires Further Human Verification 🏷️ - Compliance label |
PR Code Suggestions ✨Explore these optional code suggestions:
|
protected Broker Broker { get; private set; } | ||
|
||
internal BiDiJsonSerializerContext JsonContext { get; private set; } | ||
internal JsonSerializerContext JsonContext { get; private set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not ready to generalize it in this PR. Still not clear how to move on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have an example in this PR’s description, of how to move forward with these changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I though making Module.Create(...)
to public would be enough, please give me time to review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Observed it is theoretical changes. Let be practicable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is, except for the shared JSON context introduced in #16402
It is not theoretical changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I came to the following:
- BiDi has new method
AsModule<T>()
- PermissionsModule creates its own context based on options (and keep it as private field)
Then changes looks simple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel introducing new AsModule<T>()
method will be good for us:
- we may introduce cached modules
- it negotiates use of internal properties
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All right, AsModule<T>
is required. Built-in modules are cached, third-party modules also want to be cached per bidi
instance. Let's do it (here or in separate PR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No value,. In any case thank you.
|
||
public sealed class BrowserModule : Module | ||
{ | ||
internal new BiDiJsonSerializerContext JsonContext => (BiDiJsonSerializerContext)base.JsonContext; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RenderMichael this piece is strange, seems there is no reason to keep JsonContext in base class. If you have the same opinion, I can remake it to private field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The base class is responsible for creating the JSON context. This is the only way to bridge the gap between "strongly-typed JSON context" and the logic in Module.Create
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way to get around this is by making the Json Context a generic parameter, eg. BrowserModule : Module<BiDiJsonSerializerContext>
. That requires making BiDiJsonSerializerContext public, and more publicly exposed. I don't think that's desirable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also was thinking about BrowserModule : Module<BiDiJsonSerializerContext>
, but it seems even stranger. Module of JsonContext... I am reading it hard, given that BiDiJsonSerializerContext
cannot be inherited.
Ideally we should get rid of BiDiJsonSerializerContext
, we are moving in this direction.
About internal new BiDiJsonSerializerContext JsonContext => (BiDiJsonSerializerContext)base.JsonContext;
: For me it is risky, at least not obvious...
- is it one time initialization? (question from interview)
- what is executed first? our
void Initialize(...)
or thisimplicit initialization
- does it mean that we cast each time when we invoke
JsonContext
getter?
Private field looks really simple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to go that route, then we will have to undo optimizations such as this one: #16397
Otherwise, we will need a separate JSON context for each module
Ideally we should get rid of
BiDiJsonSerializerContext
, we are moving in this direction.
What do you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Second optimization that would need to be de-optimized: #16392
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internal modules will still use global JsonContext for a while, because of f**g cross-referencing (stateful converters, polymorphic dto). In future, each module wants to:
void Initialize(BiDi bidi, JsonOptions options) // just common options like Naming policy
{
var moduleOptions = new JsonOptions(options) // make a copy
{
Converters = { new MySpecificConverter(bidi) } // bad example, just to highlight possibilities
}
_myContext = new MyCoontext(moduleOptions);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we do cannot have a global JsonContext for third-party extensions, it looks like we will need 2 different kinds of modules: extensions and non-extension (core?).
because of f**g cross-referencing (stateful converters, polymorphic dto)
That shouldn't be a problem! We can get rid of stateful converters (very slightly less pleasant usability, I think it is no problem) and polymorphic DTOs got addressed by moving the converters out to attributes.
The only remaining converter is DateTimeOffsetConverter
. We could go through to each instance of DateTimeOffset
and add that converter as an attribute. Alternatively, we could change the type to long
in the DTO, since it is technically magic. If we want to address that, then we will have no converters left!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DateTimeOffsetConverter
is not a problem, it is kind of common JsonOptions. it is OK to have global well-known converters.
I don't want to block this PR, we can improve later. But seems private MyJsonContext
should be here. Broker
requires JsonTypeInfo
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we do cannot have a global JsonContext for third-party extensions, it looks like we will need 2 different kinds of modules: extensions and non-extension (core?).
Each module should have own JsonContext, ideally. And it is out of scope of this PR.
dotnet/src/webdriver/BiDi/Extensions/Permissions/PermissionDescriptor.cs
Outdated
Show resolved
Hide resolved
dotnet/src/webdriver/BiDi/Module.cs
Outdated
internal JsonSerializerContext JsonContext { get; private set; } | ||
|
||
protected virtual void Initialize(JsonSerializerOptions options) { } | ||
protected abstract JsonSerializerContext Initialize(JsonSerializerOptions options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should choose between void Initialize(...)
and JsonSerializerContext ConfigureJsonContext(...)
. I vote for void
, letting each module to decide whatever it wants. Input parameters might be changed in future (breaking change), but I think it will be another story.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see an issue with this, especially because we have specific requirements
- Each Module controls its own JSON context
- Modules must be able to re-use contexts from a cache
Maybe we can rename this to CreateJsonContext
, and if necessary, introduce a separate Initialize
in the future?
return bidi; | ||
} | ||
|
||
public static PermissionsModule AsPermissions(this BiDi bidi) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is definitely should be in another class. The reason is we are CLS compatible (I don't still understand why, but anyway), meaning some languages cannot deal with extension methods
. They will use static method: WebDriverExtensions.AsPermissions(bidi)
. But it is not extension of WebDriver
.
We should introduce good name for static class, and its namespace.
BiDiExtensions.AsPermissions(bidi)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When Bluetooth
module comes to under umbrella, then what? Should we have single static class for all them, or they define own static class in theirs namespace?
I vote for "everything in their namespace". It would be good pattern to demonstrate good practices how to develop module. Separate namespace is not a problem, IDE is still able to suggest extension method
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extension methods do not affect CLS compliance. Users can call WebDriverExtensions.AsPermissions(bidi)
even on extension methods.
But I agree that extensions should be in separate files. I will make those changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is about naming: WebDriverExtensions.AsPermissions(bidi)
- it is not extension for WebDriver
, it is for BiDi
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed the two suggestions: WebDriverExtensions
-> BiDiExtensions
, and permissions in its own area
…eneral BiDi extensinos
User description
🔗 Related Issues
Fixes #15329
New API surface:
PR Type
Enhancement
Description
Enable external BiDi module creation and extension
Refactor module architecture with InternalModule base class
Expose Broker and JsonOptions for external access
Simplify module creation with public static method
Diagram Walkthrough
File Walkthrough
13 files
Expose internal properties and refactor module creation
Add new base class for internal modules
Refactor to support external module creation
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule
Change inheritance to InternalModule