From 8575387b4b9d0ae6dc717b209212e1ff9bd18553 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 7 Apr 2022 13:14:49 -0700 Subject: [PATCH 1/8] callback method --- .../lib/src/common/web_kit.pigeon.dart | 89 ++++++++++++++++++ .../lib/src/web_kit/web_kit.dart | 13 +-- .../lib/src/web_kit/web_kit_api_impls.dart | 94 +++++++++++++++++++ .../pigeons/web_kit.dart | 16 ++++ .../test/src/common/test_web_kit.pigeon.dart | 24 +++++ .../src/foundation/foundation_test.mocks.dart | 2 +- .../test/src/web_kit/web_kit_test.dart | 44 +++++++++ .../test/src/web_kit/web_kit_test.mocks.dart | 6 ++ .../web_kit_webview_widget_test.mocks.dart | 2 +- 9 files changed, 282 insertions(+), 8 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart index 22013d2ff0cc..25da480ee5bb 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart @@ -1017,6 +1017,95 @@ class WKNavigationDelegateHostApi { return; } } + + Future setDidFinishNavigation( + int arg_instanceId, int? arg_functionInstanceId) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKNavigationDelegateHostApi.setDidFinishNavigation', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_instanceId, arg_functionInstanceId]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _WKNavigationDelegateFlutterApiCodec extends StandardMessageCodec { + const _WKNavigationDelegateFlutterApiCodec(); +} + +abstract class WKNavigationDelegateFlutterApi { + static const MessageCodec codec = + _WKNavigationDelegateFlutterApiCodec(); + + void dispose(int functionInstanceId); + void didFinishNavigation( + int functionInstanceId, int webViewInstanceId, String? url); + static void setup(WKNavigationDelegateFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKNavigationDelegateFlutterApi.dispose', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_functionInstanceId = (args[0] as int?); + assert(arg_functionInstanceId != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.dispose was null, expected non-null int.'); + api.dispose(arg_functionInstanceId!); + return; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKNavigationDelegateFlutterApi.didFinishNavigation', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.didFinishNavigation was null.'); + final List args = (message as List?)!; + final int? arg_functionInstanceId = (args[0] as int?); + assert(arg_functionInstanceId != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.didFinishNavigation was null, expected non-null int.'); + final int? arg_webViewInstanceId = (args[1] as int?); + assert(arg_webViewInstanceId != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.didFinishNavigation was null, expected non-null int.'); + final String? arg_url = (args[2] as String?); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.didFinishNavigation was null, expected non-null String.'); + api.didFinishNavigation( + arg_functionInstanceId!, arg_webViewInstanceId!, arg_url!); + return; + }); + } + } + } } class _NSObjectHostApiCodec extends StandardMessageCodec { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart index 0703ce1267d9..556fdecd846d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart @@ -524,6 +524,7 @@ class WKNavigationDelegate { binaryMessenger: binaryMessenger, instanceManager: instanceManager, ) { + WebKitFlutterApis.instance.ensureSetUp(); _navigationDelegateApi.createForInstances(this); } @@ -531,10 +532,7 @@ class WKNavigationDelegate { /// Called when navigation from the main frame has started. Future setDidStartProvisionalNavigation( - void Function( - WKWebView webView, - String? url, - )? + void Function(WKWebView webView, String? url)? didStartProvisionalNavigation, ) { throw UnimplementedError(); @@ -542,9 +540,12 @@ class WKNavigationDelegate { /// Called when navigation is complete. Future setDidFinishNavigation( - void Function(WKWebView webView, String? url)? didFinishNavigation, + void Function(WKWebView, String?)? didFinishNavigation, ) { - throw UnimplementedError(); + return _navigationDelegateApi.setDidFinishNavigationFromInstance( + this, + didFinishNavigation, + ); } /// Called when permission is needed to navigate to new content. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index 188f65cbe177..53ab0ff2d7c9 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import '../common/instance_manager.dart'; @@ -106,6 +107,44 @@ extension _NSUrlRequestConverter on NSUrlRequest { } } +/// Handles initialization of Flutter APIs for WebKit. +class WebKitFlutterApis { + /// Constructs a [WebKitFlutterApis]. + /// + /// This should only be changed for testing purposes. + @visibleForTesting + WebKitFlutterApis({this.binaryMessenger, InstanceManager? instanceManager}) { + navigationDelegateFlutterApi = WKNavigationDelegateFlutterApiImpl( + instanceManager: instanceManager, + ); + } + + /// Mutable instance containing all Flutter Apis for WebKit. + /// + /// This should only be changed for testing purposes. + static WebKitFlutterApis instance = WebKitFlutterApis(); + + /// Sends binary data across the Flutter platform barrier. + final BinaryMessenger? binaryMessenger; + + bool _hasBeenSetUp = false; + + /// Flutter Api for [WKNavigationDelegate]. + @visibleForTesting + late final WKNavigationDelegateFlutterApiImpl navigationDelegateFlutterApi; + + /// Ensures all the Flutter APIs have been setup to receive calls from native code. + void ensureSetUp() { + if (!_hasBeenSetUp) { + WKNavigationDelegateFlutterApi.setup( + navigationDelegateFlutterApi, + binaryMessenger: binaryMessenger, + ); + _hasBeenSetUp = true; + } + } +} + /// Host api implementation for [WKWebSiteDataStore]. class WKWebsiteDataStoreHostApiImpl extends WKWebsiteDataStoreHostApi { /// Constructs a [WebsiteDataStoreHostApiImpl]. @@ -381,6 +420,61 @@ class WKNavigationDelegateHostApiImpl extends WKNavigationDelegateHostApi { await create(instanceId); } } + + /// Calls [setDidFinishNavigation] with the ids of the provided object instances. + Future setDidFinishNavigationFromInstance( + WKNavigationDelegate instance, + void Function(WKWebView, String?)? didFinishNavigation, + ) { + int? functionInstanceId; + if (didFinishNavigation != null) { + functionInstanceId = instanceManager.getInstanceId(didFinishNavigation); + functionInstanceId ??= + instanceManager.tryAddInstance(didFinishNavigation); + } + return setDidFinishNavigation( + instanceManager.getInstanceId(instance)!, + functionInstanceId, + ); + } +} + +/// Flutter api implementation for [WKNavigationDelegate]. +class WKNavigationDelegateFlutterApiImpl + extends WKNavigationDelegateFlutterApi { + /// Constructs a [WKNavigationDelegateFlutterApiImpl]. + WKNavigationDelegateFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with native language objects. + late final InstanceManager instanceManager; + + @override + void dispose(int functionInstanceId) { + final Function? function = instanceManager.getInstance(functionInstanceId); + if (function != null) { + instanceManager.removeInstance(function); + } + } + + @override + void didFinishNavigation( + int functionInstanceId, + int webViewInstanceId, + String? url, + ) { + final void Function( + WKWebView webView, + String? url, + ) function = + instanceManager.getInstance(functionInstanceId)! as void Function( + WKWebView webView, + String? url, + ); + + function(instanceManager.getInstance(webViewInstanceId)!, url); + } } /// Host api implementation for [WKWebView]. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart index 0d5328dda8d6..4afa053bfec3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -281,6 +281,22 @@ abstract class WKScriptMessageHandlerHostApi { @HostApi(dartHostTestHandler: 'TestWKNavigationDelegateHostApi') abstract class WKNavigationDelegateHostApi { void create(int instanceId); + + void setDidFinishNavigation(int instanceId, int? functionInstanceId); +} + +/// Mirror of WKNavigationDelegate. +/// +/// See https://developer.apple.com/documentation/webkit/wknavigationdelegate?language=objc. +@FlutterApi() +abstract class WKNavigationDelegateFlutterApi { + void dispose(int functionInstanceId); + + void didFinishNavigation( + int functionInstanceId, + int webViewInstanceId, + String? url, + ); } /// Mirror of NSObject. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart index 78e4b9dcfd3d..e35f37eac826 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/test_web_kit.pigeon.dart @@ -707,6 +707,7 @@ abstract class TestWKNavigationDelegateHostApi { _TestWKNavigationDelegateHostApiCodec(); void create(int instanceId); + void setDidFinishNavigation(int instanceId, int? functionInstanceId); static void setup(TestWKNavigationDelegateHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -728,6 +729,29 @@ abstract class TestWKNavigationDelegateHostApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.WKNavigationDelegateHostApi.setDidFinishNavigation', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateHostApi.setDidFinishNavigation was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateHostApi.setDidFinishNavigation was null, expected non-null int.'); + final int? arg_functionInstanceId = (args[1] as int?); + assert(arg_functionInstanceId != null, + 'Argument for dev.flutter.pigeon.WKNavigationDelegateHostApi.setDidFinishNavigation was null, expected non-null int.'); + api.setDidFinishNavigation(arg_instanceId!, arg_functionInstanceId!); + return {}; + }); + } + } } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart index 7bd208eeac05..b8552c5d8157 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.1.0 from annotations -// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart. +// in webview_flutter_wkwebview/test/src/foundation/foundation_test.dart. // Do not manually edit this file. import 'package:mockito/mockito.dart' as _i1; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart index d51fa9793dd4..f4714eb6d484 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -9,6 +11,7 @@ import 'package:webview_flutter_wkwebview/src/common/instance_manager.dart'; import 'package:webview_flutter_wkwebview/src/common/web_kit.pigeon.dart'; import 'package:webview_flutter_wkwebview/src/foundation/foundation.dart'; import 'package:webview_flutter_wkwebview/src/web_kit/web_kit.dart'; +import 'package:webview_flutter_wkwebview/src/web_kit/web_kit_api_impls.dart'; import '../common/test_web_kit.pigeon.dart'; import 'web_kit_test.mocks.dart'; @@ -28,9 +31,12 @@ void main() { group('WebKit', () { late InstanceManager instanceManager; + late WebKitFlutterApis flutterApis; setUp(() { instanceManager = InstanceManager(); + flutterApis = WebKitFlutterApis(instanceManager: instanceManager); + WebKitFlutterApis.instance = flutterApis; }); group('$WKWebsiteDataStore', () { @@ -319,12 +325,23 @@ void main() { group('$WKNavigationDelegate', () { late MockTestWKNavigationDelegateHostApi mockPlatformHostApi; + late WKWebView webView; + late WKNavigationDelegate navigationDelegate; setUp(() async { mockPlatformHostApi = MockTestWKNavigationDelegateHostApi(); TestWKNavigationDelegateHostApi.setup(mockPlatformHostApi); + TestWKWebViewConfigurationHostApi.setup( + MockTestWKWebViewConfigurationHostApi(), + ); + TestWKWebViewHostApi.setup(MockTestWKWebViewHostApi()); + webView = WKWebView( + WKWebViewConfiguration(instanceManager: instanceManager), + instanceManager: instanceManager, + ); + navigationDelegate = WKNavigationDelegate( instanceManager: instanceManager, ); @@ -332,6 +349,8 @@ void main() { tearDown(() { TestWKNavigationDelegateHostApi.setup(null); + TestWKWebViewConfigurationHostApi.setup(null); + TestWKWebViewHostApi.setup(null); }); test('create', () async { @@ -339,6 +358,31 @@ void main() { instanceManager.getInstanceId(navigationDelegate), )); }); + + test('setDidFinishNavigation', () async { + final Completer> argsCompleter = + Completer>(); + + navigationDelegate.setDidFinishNavigation( + (WKWebView webView, String? url) { + argsCompleter.complete([webView, url]); + }, + ); + + final int functionInstanceId = + verify(mockPlatformHostApi.setDidFinishNavigation( + instanceManager.getInstanceId(navigationDelegate), + captureAny, + )).captured.single as int; + + flutterApis.navigationDelegateFlutterApi.didFinishNavigation( + functionInstanceId, + instanceManager.getInstanceId(webView)!, + 'url', + ); + + expect(argsCompleter.future, completion([webView, 'url'])); + }); }); group('$WKWebView', () { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart index a2f16317f1fe..621093d48373 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit/web_kit_test.mocks.dart @@ -33,6 +33,12 @@ class MockTestWKNavigationDelegateHostApi extends _i1.Mock void create(int? instanceId) => super.noSuchMethod(Invocation.method(#create, [instanceId]), returnValueForMissingStub: null); + @override + void setDidFinishNavigation(int? instanceId, int? functionInstanceId) => + super.noSuchMethod( + Invocation.method( + #setDidFinishNavigation, [instanceId, functionInstanceId]), + returnValueForMissingStub: null); } /// A class which mocks [TestWKPreferencesHostApi]. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart index 6c34e0c72004..00b20d5b4304 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.1.0 from annotations -// in webview_flutter_wkwebview/example/ios/.symlinks/plugins/webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart. +// in webview_flutter_wkwebview/test/src/web_kit_webview_widget_test.dart. // Do not manually edit this file. import 'dart:async' as _i5; From cbffe3ff33b42f8227616c7a45af937491fbe84d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 8 Apr 2022 14:44:34 -0700 Subject: [PATCH 2/8] create a function flutter api --- .../common/function_flutter_api_impls.dart | 25 +++++++++ .../lib/src/common/web_kit.pigeon.dart | 52 ++++++++++++------- .../src/foundation/foundation_api_impls.dart | 46 +++++++++++++++- .../lib/src/web_kit/web_kit.dart | 8 ++- .../lib/src/web_kit/web_kit_api_impls.dart | 8 --- .../pigeons/web_kit.dart | 7 ++- .../test/src/foundation/foundation_test.dart | 14 +++++ 7 files changed, 127 insertions(+), 33 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart new file mode 100644 index 000000000000..791342fc56e1 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart @@ -0,0 +1,25 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'instance_manager.dart'; +import 'web_kit.pigeon.dart'; + +/// Flutter api implementation for [NSObject]. +class FunctionFlutterApiImpl extends FunctionFlutterApi { + /// Constructs a [FunctionFlutterApiImpl]. + FunctionFlutterApiImpl({InstanceManager? instanceManager}) { + this.instanceManager = instanceManager ?? InstanceManager.instance; + } + + /// Maintains instances stored to communicate with native language objects. + late final InstanceManager instanceManager; + + @override + void dispose(int instanceId) { + final Function? function = instanceManager.getInstance(instanceId); + if (function != null) { + instanceManager.removeInstance(function); + } + } +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart index 25da480ee5bb..42f2ea344286 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.pigeon.dart @@ -1054,30 +1054,10 @@ abstract class WKNavigationDelegateFlutterApi { static const MessageCodec codec = _WKNavigationDelegateFlutterApiCodec(); - void dispose(int functionInstanceId); void didFinishNavigation( int functionInstanceId, int webViewInstanceId, String? url); static void setup(WKNavigationDelegateFlutterApi? api, {BinaryMessenger? binaryMessenger}) { - { - final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.WKNavigationDelegateFlutterApi.dispose', codec, - binaryMessenger: binaryMessenger); - if (api == null) { - channel.setMessageHandler(null); - } else { - channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.dispose was null.'); - final List args = (message as List?)!; - final int? arg_functionInstanceId = (args[0] as int?); - assert(arg_functionInstanceId != null, - 'Argument for dev.flutter.pigeon.WKNavigationDelegateFlutterApi.dispose was null, expected non-null int.'); - api.dispose(arg_functionInstanceId!); - return; - }); - } - } { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.WKNavigationDelegateFlutterApi.didFinishNavigation', @@ -1226,6 +1206,38 @@ class NSObjectHostApi { } } +class _FunctionFlutterApiCodec extends StandardMessageCodec { + const _FunctionFlutterApiCodec(); +} + +abstract class FunctionFlutterApi { + static const MessageCodec codec = _FunctionFlutterApiCodec(); + + void dispose(int instanceId); + static void setup(FunctionFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.FunctionFlutterApi.dispose', codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.FunctionFlutterApi.dispose was null.'); + final List args = (message as List?)!; + final int? arg_instanceId = (args[0] as int?); + assert(arg_instanceId != null, + 'Argument for dev.flutter.pigeon.FunctionFlutterApi.dispose was null, expected non-null int.'); + api.dispose(arg_instanceId!); + return; + }); + } + } + } +} + class _WKWebViewHostApiCodec extends StandardMessageCodec { const _WKWebViewHostApiCodec(); @override diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart index ec0d60cc748e..c22299ddd1f9 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart @@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import '../common/function_flutter_api_impls.dart'; import '../common/instance_manager.dart'; import '../common/web_kit.pigeon.dart'; import 'foundation.dart'; @@ -35,6 +37,46 @@ Iterable }); } +/// Handles initialization of Flutter APIs for the Foundation library. +class FoundationFlutterApis { + /// Constructs a [FoundationFlutterApis]. + /// + /// This should only be changed for testing purposes. + @visibleForTesting + FoundationFlutterApis({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) { + functionFlutterApi = + FunctionFlutterApiImpl(instanceManager: instanceManager); + } + + /// Mutable instance containing all Flutter Apis for the Foundation library. + /// + /// This should only be changed for testing purposes. + static FoundationFlutterApis instance = FoundationFlutterApis(); + + /// Sends binary data across the Flutter platform barrier. + final BinaryMessenger? binaryMessenger; + + bool _hasBeenSetUp = false; + + /// Flutter Api for [NSObject]. + @visibleForTesting + late final FunctionFlutterApiImpl functionFlutterApi; + + /// Ensures all the Flutter APIs have been setup to receive calls from native code. + void ensureSetUp() { + if (!_hasBeenSetUp) { + FunctionFlutterApi.setup( + functionFlutterApi, + binaryMessenger: binaryMessenger, + ); + _hasBeenSetUp = true; + } + } +} + /// Host api implementation for [NSObject]. class NSObjectHostApiImpl extends NSObjectHostApi { /// Constructs an [NSObjectHostApiImpl]. @@ -42,7 +84,9 @@ class NSObjectHostApiImpl extends NSObjectHostApi { BinaryMessenger? binaryMessenger, InstanceManager? instanceManager, }) : instanceManager = instanceManager ?? InstanceManager.instance, - super(binaryMessenger: binaryMessenger); + super(binaryMessenger: binaryMessenger) { + FoundationFlutterApis.instance.ensureSetUp(); + } /// Maintains instances stored to communicate with Objective-C objects. final InstanceManager instanceManager; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart index 556fdecd846d..515715461679 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart @@ -515,12 +515,16 @@ class WKUIDelegate { /// coordinate changes in your web view’s main frame. /// /// Wraps [WKNavigationDelegate](https://developer.apple.com/documentation/webkit/wknavigationdelegate?language=objc). -class WKNavigationDelegate { +class WKNavigationDelegate extends NSObject { /// Constructs a [WKNavigationDelegate]. WKNavigationDelegate({ BinaryMessenger? binaryMessenger, InstanceManager? instanceManager, - }) : _navigationDelegateApi = WKNavigationDelegateHostApiImpl( + }) : _navigationDelegateApi = WKNavigationDelegateHostApiImpl( + binaryMessenger: binaryMessenger, + instanceManager: instanceManager, + ), + super( binaryMessenger: binaryMessenger, instanceManager: instanceManager, ) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index 53ab0ff2d7c9..03932958f35c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -450,14 +450,6 @@ class WKNavigationDelegateFlutterApiImpl /// Maintains instances stored to communicate with native language objects. late final InstanceManager instanceManager; - @override - void dispose(int functionInstanceId) { - final Function? function = instanceManager.getInstance(functionInstanceId); - if (function != null) { - instanceManager.removeInstance(function); - } - } - @override void didFinishNavigation( int functionInstanceId, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart index 4afa053bfec3..b138858e1177 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -290,8 +290,6 @@ abstract class WKNavigationDelegateHostApi { /// See https://developer.apple.com/documentation/webkit/wknavigationdelegate?language=objc. @FlutterApi() abstract class WKNavigationDelegateFlutterApi { - void dispose(int functionInstanceId); - void didFinishNavigation( int functionInstanceId, int webViewInstanceId, @@ -316,6 +314,11 @@ abstract class NSObjectHostApi { void removeObserver(int instanceId, int observerInstanceId, String keyPath); } +@FlutterApi() +abstract class FunctionFlutterApi { + void dispose(int instanceId); +} + /// Mirror of WKWebView. /// /// See https://developer.apple.com/documentation/webkit/wkwebview?language=objc. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart index a08680940bcc..872b248b6da8 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart @@ -8,6 +8,7 @@ import 'package:mockito/mockito.dart'; import 'package:webview_flutter_wkwebview/src/common/instance_manager.dart'; import 'package:webview_flutter_wkwebview/src/common/web_kit.pigeon.dart'; import 'package:webview_flutter_wkwebview/src/foundation/foundation.dart'; +import 'package:webview_flutter_wkwebview/src/foundation/foundation_api_impls.dart'; import '../common/test_web_kit.pigeon.dart'; import 'foundation_test.mocks.dart'; @@ -25,6 +26,19 @@ void main() { instanceManager = InstanceManager(); }); + test('$FunctionFlutterApi dispose', () { + final Function function = () {}; + final int functionInstanceId = instanceManager.tryAddInstance(function)!; + + FoundationFlutterApis.instance = FoundationFlutterApis( + instanceManager: instanceManager, + )..ensureSetUp(); + + FoundationFlutterApis.instance.functionFlutterApi + .dispose(functionInstanceId); + expect(instanceManager.getInstanceId(function), isNull); + }); + group('$NSObject', () { late MockTestNSObjectHostApi mockPlatformHostApi; From 3537176b7275f62755400925725a1d06c969bfae Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 8 Apr 2022 14:50:49 -0700 Subject: [PATCH 3/8] fixes --- .../common/function_flutter_api_impls.dart | 2 +- .../src/foundation/foundation_api_impls.dart | 2 +- .../pigeons/web_kit.dart | 1 + .../src/common/function_flutter_api_test.dart | 33 +++++++++++++++++++ .../test/src/foundation/foundation_test.dart | 14 -------- 5 files changed, 36 insertions(+), 16 deletions(-) create mode 100644 packages/webview_flutter/webview_flutter_wkwebview/test/src/common/function_flutter_api_test.dart diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart index 791342fc56e1..c6eb711513d2 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/function_flutter_api_impls.dart @@ -5,7 +5,7 @@ import 'instance_manager.dart'; import 'web_kit.pigeon.dart'; -/// Flutter api implementation for [NSObject]. +/// Flutter api to dispose functions. class FunctionFlutterApiImpl extends FunctionFlutterApi { /// Constructs a [FunctionFlutterApiImpl]. FunctionFlutterApiImpl({InstanceManager? instanceManager}) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart index c22299ddd1f9..c5c6bd80af9d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart @@ -61,7 +61,7 @@ class FoundationFlutterApis { bool _hasBeenSetUp = false; - /// Flutter Api for [NSObject]. + /// Flutter Api for disposing functions. @visibleForTesting late final FunctionFlutterApiImpl functionFlutterApi; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart index b138858e1177..12a9237a9a97 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -314,6 +314,7 @@ abstract class NSObjectHostApi { void removeObserver(int instanceId, int observerInstanceId, String keyPath); } +/// Disposes references to functions. @FlutterApi() abstract class FunctionFlutterApi { void dispose(int instanceId); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/function_flutter_api_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/function_flutter_api_test.dart new file mode 100644 index 000000000000..63e59386ceaf --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/common/function_flutter_api_test.dart @@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; +import 'package:webview_flutter_wkwebview/src/common/instance_manager.dart'; +import 'package:webview_flutter_wkwebview/src/common/web_kit.pigeon.dart'; +import 'package:webview_flutter_wkwebview/src/foundation/foundation_api_impls.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('$FunctionFlutterApi', () { + late InstanceManager instanceManager; + + setUp(() { + instanceManager = InstanceManager(); + }); + + test('dispose', () { + final Function function = () {}; + final int functionInstanceId = instanceManager.tryAddInstance(function)!; + + FoundationFlutterApis.instance = FoundationFlutterApis( + instanceManager: instanceManager, + )..ensureSetUp(); + + FoundationFlutterApis.instance.functionFlutterApi + .dispose(functionInstanceId); + expect(instanceManager.getInstanceId(function), isNull); + }); + }); +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart index 872b248b6da8..a08680940bcc 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/src/foundation/foundation_test.dart @@ -8,7 +8,6 @@ import 'package:mockito/mockito.dart'; import 'package:webview_flutter_wkwebview/src/common/instance_manager.dart'; import 'package:webview_flutter_wkwebview/src/common/web_kit.pigeon.dart'; import 'package:webview_flutter_wkwebview/src/foundation/foundation.dart'; -import 'package:webview_flutter_wkwebview/src/foundation/foundation_api_impls.dart'; import '../common/test_web_kit.pigeon.dart'; import 'foundation_test.mocks.dart'; @@ -26,19 +25,6 @@ void main() { instanceManager = InstanceManager(); }); - test('$FunctionFlutterApi dispose', () { - final Function function = () {}; - final int functionInstanceId = instanceManager.tryAddInstance(function)!; - - FoundationFlutterApis.instance = FoundationFlutterApis( - instanceManager: instanceManager, - )..ensureSetUp(); - - FoundationFlutterApis.instance.functionFlutterApi - .dispose(functionInstanceId); - expect(instanceManager.getInstanceId(function), isNull); - }); - group('$NSObject', () { late MockTestNSObjectHostApi mockPlatformHostApi; From 494fe560f9769a5a12d1ee277e89f9c529f4c341 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 8 Apr 2022 14:53:30 -0700 Subject: [PATCH 4/8] include names --- .../webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart | 2 +- .../lib/src/web_kit/web_kit_api_impls.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart index 515715461679..2775507a0427 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit.dart @@ -544,7 +544,7 @@ class WKNavigationDelegate extends NSObject { /// Called when navigation is complete. Future setDidFinishNavigation( - void Function(WKWebView, String?)? didFinishNavigation, + void Function(WKWebView webView, String? url)? didFinishNavigation, ) { return _navigationDelegateApi.setDidFinishNavigationFromInstance( this, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index 03932958f35c..21da73c4b8bd 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import '../common/instance_manager.dart'; From 370c418331d4703d94bf7699815765a47bad6e08 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 12 Apr 2022 10:50:31 -0700 Subject: [PATCH 5/8] move ensure to the class --- .../lib/src/foundation/foundation.dart | 4 +++- .../lib/src/foundation/foundation_api_impls.dart | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart index 8aa315aa10ee..e1da84d6b247 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart @@ -149,7 +149,9 @@ class NSObject { : _api = NSObjectHostApiImpl( binaryMessenger: binaryMessenger, instanceManager: instanceManager, - ); + ) { + FoundationFlutterApis.instance.ensureSetUp(); + } final NSObjectHostApiImpl _api; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart index c5c6bd80af9d..dfb0291935ee 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart @@ -84,9 +84,7 @@ class NSObjectHostApiImpl extends NSObjectHostApi { BinaryMessenger? binaryMessenger, InstanceManager? instanceManager, }) : instanceManager = instanceManager ?? InstanceManager.instance, - super(binaryMessenger: binaryMessenger) { - FoundationFlutterApis.instance.ensureSetUp(); - } + super(binaryMessenger: binaryMessenger); /// Maintains instances stored to communicate with Objective-C objects. final InstanceManager instanceManager; From 5363b9a7d0819d38035f111493550223cff38945 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 12 Apr 2022 12:46:51 -0700 Subject: [PATCH 6/8] PR feedback --- .../lib/src/foundation/foundation.dart | 2 + .../src/foundation/foundation_api_impls.dart | 32 +++++++----- .../lib/src/web_kit/web_kit_api_impls.dart | 50 ++++++++++--------- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart index e1da84d6b247..1dc15e4e711b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart @@ -150,6 +150,8 @@ class NSObject { binaryMessenger: binaryMessenger, instanceManager: instanceManager, ) { + // Ensures FlutterApis for the Foundation library and FunctionFlutterApi are + // setup. FoundationFlutterApis.instance.ensureSetUp(); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart index dfb0291935ee..b007d1a8312c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation_api_impls.dart @@ -40,37 +40,45 @@ Iterable /// Handles initialization of Flutter APIs for the Foundation library. class FoundationFlutterApis { /// Constructs a [FoundationFlutterApis]. - /// - /// This should only be changed for testing purposes. @visibleForTesting FoundationFlutterApis({ - this.binaryMessenger, + BinaryMessenger? binaryMessenger, InstanceManager? instanceManager, - }) { + }) : _binaryMessenger = binaryMessenger { functionFlutterApi = FunctionFlutterApiImpl(instanceManager: instanceManager); } - /// Mutable instance containing all Flutter Apis for the Foundation library. - /// - /// This should only be changed for testing purposes. - static FoundationFlutterApis instance = FoundationFlutterApis(); + static FoundationFlutterApis _instance = FoundationFlutterApis(); + + /// Sets the global instance containing the Flutter Apis for the Foundation library. + @visibleForTesting + static set instance(FoundationFlutterApis instance) { + _instance = instance; + } - /// Sends binary data across the Flutter platform barrier. - final BinaryMessenger? binaryMessenger; + /// Global instance containing the Flutter Apis for the Foundation library. + static FoundationFlutterApis get instance { + return _instance; + } + final BinaryMessenger? _binaryMessenger; bool _hasBeenSetUp = false; /// Flutter Api for disposing functions. + /// + /// This FlutterApi is placed here because [FoundationFlutterApis.ensureSetUp] + /// is called inside [NSObject] and [NSObject] is the parent class of all + /// objects. @visibleForTesting late final FunctionFlutterApiImpl functionFlutterApi; - /// Ensures all the Flutter APIs have been setup to receive calls from native code. + /// Ensures all the Flutter APIs have been set up to receive calls from native code. void ensureSetUp() { if (!_hasBeenSetUp) { FunctionFlutterApi.setup( functionFlutterApi, - binaryMessenger: binaryMessenger, + binaryMessenger: _binaryMessenger, ); _hasBeenSetUp = true; } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index 21da73c4b8bd..82e269ed32bd 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -10,6 +10,11 @@ import '../common/web_kit.pigeon.dart'; import '../foundation/foundation.dart'; import 'web_kit.dart'; +typedef _NavigationCallback = void Function( + WKWebView webView, + String? url, +); + Iterable _toWKWebsiteDataTypesEnumData( Iterable types) { return types.map((WKWebsiteDataTypes type) { @@ -110,35 +115,42 @@ extension _NSUrlRequestConverter on NSUrlRequest { /// Handles initialization of Flutter APIs for WebKit. class WebKitFlutterApis { /// Constructs a [WebKitFlutterApis]. - /// - /// This should only be changed for testing purposes. @visibleForTesting - WebKitFlutterApis({this.binaryMessenger, InstanceManager? instanceManager}) { + WebKitFlutterApis({ + BinaryMessenger? binaryMessenger, + InstanceManager? instanceManager, + }) : _binaryMessenger = binaryMessenger { navigationDelegateFlutterApi = WKNavigationDelegateFlutterApiImpl( instanceManager: instanceManager, ); } - /// Mutable instance containing all Flutter Apis for WebKit. - /// - /// This should only be changed for testing purposes. - static WebKitFlutterApis instance = WebKitFlutterApis(); + static WebKitFlutterApis _instance = WebKitFlutterApis(); - /// Sends binary data across the Flutter platform barrier. - final BinaryMessenger? binaryMessenger; + /// Sets the global instance containing the Flutter Apis for the WebKit library. + @visibleForTesting + static set instance(WebKitFlutterApis instance) { + _instance = instance; + } + /// Global instance containing the Flutter Apis for the WebKit library. + static WebKitFlutterApis get instance { + return _instance; + } + + final BinaryMessenger? _binaryMessenger; bool _hasBeenSetUp = false; /// Flutter Api for [WKNavigationDelegate]. @visibleForTesting late final WKNavigationDelegateFlutterApiImpl navigationDelegateFlutterApi; - /// Ensures all the Flutter APIs have been setup to receive calls from native code. + /// Ensures all the Flutter APIs have been set up to receive calls from native code. void ensureSetUp() { if (!_hasBeenSetUp) { WKNavigationDelegateFlutterApi.setup( navigationDelegateFlutterApi, - binaryMessenger: binaryMessenger, + binaryMessenger: _binaryMessenger, ); _hasBeenSetUp = true; } @@ -428,9 +440,8 @@ class WKNavigationDelegateHostApiImpl extends WKNavigationDelegateHostApi { ) { int? functionInstanceId; if (didFinishNavigation != null) { - functionInstanceId = instanceManager.getInstanceId(didFinishNavigation); - functionInstanceId ??= - instanceManager.tryAddInstance(didFinishNavigation); + functionInstanceId = instanceManager.getInstanceId(didFinishNavigation) ?? + instanceManager.tryAddInstance(didFinishNavigation)!; } return setDidFinishNavigation( instanceManager.getInstanceId(instance)!, @@ -456,15 +467,8 @@ class WKNavigationDelegateFlutterApiImpl int webViewInstanceId, String? url, ) { - final void Function( - WKWebView webView, - String? url, - ) function = - instanceManager.getInstance(functionInstanceId)! as void Function( - WKWebView webView, - String? url, - ); - + final _NavigationCallback function = + instanceManager.getInstance(functionInstanceId)! as _NavigationCallback; function(instanceManager.getInstance(webViewInstanceId)!, url); } } From 009bb9db3522a40838aa64a9987b7e33d903504c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 12 Apr 2022 16:02:12 -0700 Subject: [PATCH 7/8] no casting --- .../lib/src/web_kit/web_kit_api_impls.dart | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart index 82e269ed32bd..40b0f872d37b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/web_kit/web_kit_api_impls.dart @@ -10,11 +10,6 @@ import '../common/web_kit.pigeon.dart'; import '../foundation/foundation.dart'; import 'web_kit.dart'; -typedef _NavigationCallback = void Function( - WKWebView webView, - String? url, -); - Iterable _toWKWebsiteDataTypesEnumData( Iterable types) { return types.map((WKWebsiteDataTypes type) { @@ -467,8 +462,10 @@ class WKNavigationDelegateFlutterApiImpl int webViewInstanceId, String? url, ) { - final _NavigationCallback function = - instanceManager.getInstance(functionInstanceId)! as _NavigationCallback; + final void Function( + WKWebView webView, + String? url, + ) function = instanceManager.getInstance(functionInstanceId)!; function(instanceManager.getInstance(webViewInstanceId)!, url); } } From 9e3f95184e31a955bece7de37f0349e3e9197e03 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 14 Apr 2022 16:04:39 -0700 Subject: [PATCH 8/8] set up --- .../lib/src/foundation/foundation.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart index 1dc15e4e711b..24dd55ac3ec8 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/foundation/foundation.dart @@ -151,7 +151,7 @@ class NSObject { instanceManager: instanceManager, ) { // Ensures FlutterApis for the Foundation library and FunctionFlutterApi are - // setup. + // set up. FoundationFlutterApis.instance.ensureSetUp(); }