-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[webview_flutter] platform_interface: Use Dart objects for creationParams and webSettings. #1624
Conversation
cyanglaz
left a comment
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 like this approach, I was planning to do a similar update to the image_picker as well.
Left some comments.
| this.debuggingEnabled, | ||
| }); | ||
|
|
||
| final JavascriptMode javascriptMode; |
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.
nit: dart doc?
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.
done
| final JavascriptMode javascriptMode; | ||
|
|
||
| /// Whether a [NavigationDelegate] should be used for this webview. | ||
| final bool hasNavigationDelegate; |
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.
nit(personal opinion): useNavigationDelegate might be a better name in this case.
| // https://github.com/flutter/flutter/issues/26431 | ||
| // ignore: strong_mode_implicit_dynamic_method | ||
| final Map<String, dynamic> updatesMap = _webSettingsToMap(settings); | ||
| if (updatesMap.isEmpty) { |
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 option could be assert(!updatesMap.isEmpty)
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's actually legit to send a settings with all null fields to this method.
We could potentially move the short-circuting logic to webview_flutter.dart, but that requires some ugliness or maintaining an operator== for WebSettings which I'm hesitant to do from a forward-compatibility point of view(I can see us adding a list field to WebSettings, at which point naive looking webSettings==webSettings2 might actually be expensive.
| JavascriptMode javascriptMode; | ||
| bool hasNavigationDelegate; | ||
| bool debuggingEnabled; | ||
| if (currentValue.javascriptMode != newValue.javascriptMode) { |
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 the newValue.javascriptMode is null and the currentValue.javascriptMode is non-null, we are setting the old value to null. Same as below. It seems to violate the comment here:
/// Updates the webview settings.
///
/// Any non null field in `settings` will be set as the new setting value.
/// All null fields in `settings` are ignored.
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.
+1
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 fields in currentValue should never be null (the initial value built by _WebSettingFromWidget can never have null values).
I made it clear in the method comment and added assertions.
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 was thinking when the fields in newValue is null, the current implementation will set the corresponding fields in the currentValue to null. But the dart doc in the updateSetting in the WebViewSettings class mentioned that the null fields should be ignored.
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.
After offline discussion with @amirh; we confirmed that the fields in both currentValue and newValue could never be null because they are both created by _webSettingsFromWidget which takes the setting from the WebView widget, which should never be null. Can possibly add assertions.
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.
Added more assertions here
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.
Sorry I'm a bit confused about this entire method, what it's purpose? It looks to me that the return type will almost always be a copy of newValue unless the fields of each equal, in which case it will return a new WebSettings object with some null fields - is that really what you want?
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.
On the platform side, at least for the platforms we've been dealing with so far, all these "settings" are updated by imperative calls, e.g on Android we call setJavaScriptEnabled to update the "javascriptMode".
We do not want to call setJavaScriptEnabled every time the widget is rebuilt, so we're keeping track of the previous javascriptMode value we had the last time the widget was built, and only when we see that the value has changed we call setJavaScriptEnabled.
The WebSettings class groups these kind of settings. We track the previous WebSettings value, and when the widget is rebuilt this method(_webSettingsUpdate) computes a WebSettings instance that only includes the values that have changed and has to be updated on the platform side. This value is then passed to WebViewPlatform.updateSettings which ignores the null fields and updates the platform webview with the new values for all non-null fields in WebSettings.
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 see, so you're nullfying all the unchanged fields on purpose because WebViewPlatform.updateSettings expects it that way. I guess the method name confused me, it's more like nullfyUnchangedValues which is a horrible name I agree. Anyway, thanks for the detailed explanation.
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.
Renamed to _clearUnchangedWebSettings
| /// Whether to enable the platform's webview content debugging tools. | ||
| /// | ||
| /// See also: [WebView.debuggingEnabled]. | ||
| final bool debuggingEnabled; |
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.
nit: isDebuggingEnabled
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 think it makes sense to keep it consistent with the WebView parameter name, if we want to change both it will be a breaking change at this point.
Note that as far as I know the Flutter style guide doesn't prefer an "is" prefix for flags.
|
|
||
| /// The initial set of JavaScript channels that are configured for this webview. | ||
| /// | ||
| /// For each value in this list the platform's webview should make sure that a corresponding |
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.
nit: "in this 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.
done
| } | ||
|
|
||
|
|
||
| static Map<String, dynamic> creationParamsToMap(CreationParams creationParams) { |
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.
add dart doc or should it be private?
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.
done
| JavascriptMode javascriptMode; | ||
| bool hasNavigationDelegate; | ||
| bool debuggingEnabled; | ||
| if (currentValue.javascriptMode != newValue.javascriptMode) { |
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.
+1
amirh
left a comment
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.
Thanks! PTAL
| JavascriptMode javascriptMode; | ||
| bool hasNavigationDelegate; | ||
| bool debuggingEnabled; | ||
| if (currentValue.javascriptMode != newValue.javascriptMode) { |
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 fields in currentValue should never be null (the initial value built by _WebSettingFromWidget can never have null values).
I made it clear in the method comment and added assertions.
| // https://github.com/flutter/flutter/issues/26431 | ||
| // ignore: strong_mode_implicit_dynamic_method | ||
| final Map<String, dynamic> updatesMap = _webSettingsToMap(settings); | ||
| if (updatesMap.isEmpty) { |
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's actually legit to send a settings with all null fields to this method.
We could potentially move the short-circuting logic to webview_flutter.dart, but that requires some ugliness or maintaining an operator== for WebSettings which I'm hesitant to do from a forward-compatibility point of view(I can see us adding a list field to WebSettings, at which point naive looking webSettings==webSettings2 might actually be expensive.
| } | ||
|
|
||
|
|
||
| static Map<String, dynamic> creationParamsToMap(CreationParams creationParams) { |
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.
done
|
|
||
| /// The initial set of JavaScript channels that are configured for this webview. | ||
| /// | ||
| /// For each value in this list the platform's webview should make sure that a corresponding |
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.
done
| /// Whether to enable the platform's webview content debugging tools. | ||
| /// | ||
| /// See also: [WebView.debuggingEnabled]. | ||
| final bool debuggingEnabled; |
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 think it makes sense to keep it consistent with the WebView parameter name, if we want to change both it will be a breaking change at this point.
Note that as far as I know the Flutter style guide doesn't prefer an "is" prefix for flags.
| this.debuggingEnabled, | ||
| }); | ||
|
|
||
| final JavascriptMode javascriptMode; |
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.
done
cyanglaz
left a comment
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.
|
Thanks. |
| JavascriptMode javascriptMode; | ||
| bool hasNavigationDelegate; | ||
| bool debuggingEnabled; | ||
| if (currentValue.javascriptMode != newValue.javascriptMode) { |
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 see, so you're nullfying all the unchanged fields on purpose because WebViewPlatform.updateSettings expects it that way. I guess the method name confused me, it's more like nullfyUnchangedValues which is a horrible name I agree. Anyway, thanks for the detailed explanation.
As a temporary step we passed these objects as maps that were sent across the method channel. This PR replaces the maps with proper Dart objects.
9cecb36 to
b05a5c6
Compare
…ce (#1645) This is a followup for #1618 and #1624, and moves all of the plugins.flutter.io/webview method channel calls behind the platform channel, which allows a third party package to provide a new platform implementation for all of these methods. See the description for #1618 for more details. The last remaining part is the plugins.flutter.io/cookie_manager channel which I'm leaving for a followup PR.
This is a followup for #1618, #1624, and #1645, and moves the plugins.flutter.io/cookie_manager method channel behind the platform interface which allows a third party package to provide a new platform implementation the cooke manager. See the description for #1618 for more details. Following this PR all platform specific code can be replaced by an external package.

As a temporary step we passed these objects as maps that were sent across the method channel. This PR replaces the maps with proper Dart objects.