-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Adds support for JavaScript channels to the new iOS implementation of webview_flutter_wkwebview
.
#4782
Conversation
@@ -140,18 +146,89 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { | |||
if (!requiresUserAction) WKAudiovisualMediaType.none, | |||
}; | |||
} | |||
|
|||
@override | |||
Future<void> addJavascriptChannels(Set<String> javascriptChannelNames) async { |
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.
Relevant code from current implementation: https://github.com/flutter/plugins/blob/main/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m#L424
} | ||
|
||
@override | ||
Future<void> removeJavascriptChannels( |
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.
relevant code from current implementation: https://github.com/flutter/plugins/blob/main/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m#L433
}) : super(callbacksHandler) { | ||
_setCreationParams( | ||
creationParams, | ||
configuration: configuration ?? WKWebViewConfiguration(), | ||
).then((_) => _initializationCompleter.complete()); |
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 method doesn't actually wait for any Future
and _initializationCompleter
is not used. I missed this in the PR before this one.
} | ||
|
||
final Completer<void> _initializationCompleter = Completer<void>(); |
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.
unused
/// | ||
/// This should only be used for testing purposes. | ||
@visibleForTesting | ||
class WebViewProxy { |
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.
Name change since this class constructs more than just WKWebView
.
@@ -49,7 +59,6 @@ void main() { | |||
CreationParams? creationParams, | |||
bool hasNavigationDelegate = false, | |||
bool hasProgressTracking = false, | |||
bool useHybridComposition = false, |
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.
unused
webview_flutter_wkwebview
.
/// An interface for receiving messages from JavaScript code running in a webpage. | ||
/// | ||
/// Wraps [WKScriptMessageHandler](https://developer.apple.com/documentation/webkit/wkscriptmessagehandler?language=objc) | ||
class WKScriptMessageHandler { |
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.
Is making this a class actually useful? A one-method protocol seems like it would be more simply represented by a function typedef. You could even name that typedef WKScriptMessageHandler.
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.
(Especially since you've converted the protocol method to a lambda anyway.)
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 idea since it would make this simpler and easier to test. But my main concern would be that this protocol could eventually be updated with a new method, then we would have to convert it back to a class. Although this would be relatively trivial to do; ~50 line change.
So I wonder if you think it's better to play it safe and avoid larger changes in the future or use our intuition to convert one-method classes/protocols to typedefs. Java uses a lot of one method interfaces, so this policy could definitely apply to the Android code as well.
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 that since it was entirely internal it wouldn't be a big deal if we had to convert it to a class (if it were public I'd definitely say we should keep this version). But I guess in cases where we did have to do that conversion later it would undermine your design goal of this approach of putting the language boundary as close to the OS APIs as possible in order to make updating it for small OS API changes a simple, mechanical change.
I guess it really becomes a gamble about whether we think new methods are likely or not. It's tricky since the pattern of using protocols for delegation, rather than blocks, is baked pretty deeply into ObjC norms, so the existence of a protocol isn't really an indication of whether the designers expect to add more methods.
I'll leave it to you to decide since I think there are good arguments both ways here, and the main deciding factor is unknowable.
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 preference is to play it safe so that it can remain easy to maintain for future maintainers and community developers. So I'll keep it as is for now.
_setWebViewConfiguration( | ||
configuration, | ||
allowsInlineMediaPlayback: params.webSettings?.allowsInlineMediaPlayback, | ||
autoMediaPlaybackPolicy: params.autoMediaPlaybackPolicy, | ||
); | ||
|
||
webView = webViewProxy.createWebView(configuration); | ||
|
||
addJavascriptChannels(params.javascriptChannelNames); |
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.
Why don't we want to await this, and keep the surrounding method async?
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.
Ah, good catch. I forgot I added this method. I changed the method to be async again. However, its only use is in the constructor so it won't be awaited.
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.
LGTM
final Set<String> remainingNames = _scriptMessageHandlers.keys.toSet(); | ||
_scriptMessageHandlers.clear(); | ||
|
||
return addJavascriptChannels(remainingNames); |
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: Since this is a (Future) void function, wouldn't it be more idiomatic to await
rather than return
here?
…ntation of `webview_flutter_wkwebview`. (flutter/plugins#4782)
Adds support for JavaScript channels to the new iOS implementation.
No version change:
Part of flutter/flutter#93732 and doesn't make any changes to the current implementation.
No CHANGELOG change: Incremental unused code doesn't need to be noted in the CHANGELOG.
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.