From e25faa34b38216dda47623eb32a49084d350b65d Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 1 Oct 2021 15:02:09 +0200 Subject: [PATCH 01/36] [webview_flutter_platform_interface] Update webview platform interface with new methods for running JavaScript --- .../CHANGELOG.md | 4 +++ .../webview_method_channel.dart | 12 +++++++ .../webview_platform_controller.dart | 17 +++++++++ .../pubspec.yaml | 2 +- .../webview_method_channel_test.dart | 36 +++++++++++++++++++ 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index 9e217a04e961..5a37994f4fa3 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0 + +* Added `runJavaScript` and `runJavaScriptForResult` interface methods to supersede `evaluateJavaScript`. + ## 1.0.0 * Extracted platform interface from `webview_flutter`. \ No newline at end of file diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart index b467daf72a08..29cb1bdde798 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart @@ -129,6 +129,18 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { .then((result) => result!); } + @override + Future runJavaScript(String javaScriptString) async { + await _channel.invokeMethod('runJavaScript', javaScriptString); + } + + @override + Future runJavaScriptForResult(String javaScriptString) { + return _channel + .invokeMethod('runJavaScriptForResult', javaScriptString) + .then((result) => result!); + } + @override Future addJavascriptChannels(Set javascriptChannelNames) { return _channel.invokeMethod( diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart index 319ca7e7a845..6ccba8b63fb0 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart @@ -112,6 +112,23 @@ abstract class WebViewPlatformController { "WebView evaluateJavascript is not implemented on the current platform"); } + /// Runs the given JavaScript in the context of the current page. + /// + /// The Future completes with an error if a JavaScript error occurred. + Future runJavaScript(String javaScriptString) { + throw UnimplementedError( + "WebView runJavaScript is not implemented on the current platform"); + } + + /// Runs the given JavaScript in the context of the current page, and returns the result. + /// + /// The Future completes with an error if a JavaScript error occurred, or successfully completes with a null value + /// if the type of the value is not supported(e.g on iOS not all non primitive type can be evaluated). + Future runJavaScriptForResult(String javaScriptString) { + throw UnimplementedError( + "WebView runJavaScriptForResult is not implemented on the current platform"); + } + /// Adds new JavaScript channels to the set of enabled channels. /// /// For each value in this list the platform's webview should make sure that a corresponding diff --git a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml index bf43c265d77a..166c55b133db 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/plugins/tree/master/packages/webview_flut issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview_flutter%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 1.0.0 +version: 1.1.0 environment: sdk: ">=2.12.0 <3.0.0" diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart index 2f845eaa4999..9a0167821d2f 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart @@ -280,6 +280,42 @@ void main() { ); }); + test('evaluateJavascript', () async { + final String evaluateJavascript = + await webViewPlatform.evaluateJavascript( + 'This simulates some Javascript code.', + ); + + expect('This simulates some Javascript code.', evaluateJavascript); + expect( + log, + [ + isMethodCall( + 'evaluateJavascript', + arguments: 'This simulates some Javascript code.', + ), + ], + ); + }); + + test('evaluateJavascript', () async { + final String evaluateJavascript = + await webViewPlatform.evaluateJavascript( + 'This simulates some Javascript code.', + ); + + expect('This simulates some Javascript code.', evaluateJavascript); + expect( + log, + [ + isMethodCall( + 'evaluateJavascript', + arguments: 'This simulates some Javascript code.', + ), + ], + ); + }); + test('addJavascriptChannels', () async { final Set channels = {'channel one', 'channel two'}; await webViewPlatform.addJavascriptChannels(channels); From f19b5c3666581110b073c11f7639427a0c76a8ad Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 1 Oct 2021 15:12:46 +0200 Subject: [PATCH 02/36] Fix tests --- .../webview_method_channel_test.dart | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart index 9a0167821d2f..358eaf9aa396 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart @@ -31,6 +31,7 @@ void main() { case 'canGoBack': case 'canGoForward': return true; + case 'runJavaScriptForResult': case 'evaluateJavascript': return methodCall.arguments as String; case 'getScrollX': @@ -280,27 +281,25 @@ void main() { ); }); - test('evaluateJavascript', () async { - final String evaluateJavascript = - await webViewPlatform.evaluateJavascript( + test('runJavaScript', () async { + await webViewPlatform.runJavaScript( 'This simulates some Javascript code.', ); - expect('This simulates some Javascript code.', evaluateJavascript); expect( log, [ isMethodCall( - 'evaluateJavascript', + 'runJavaScript', arguments: 'This simulates some Javascript code.', ), ], ); }); - test('evaluateJavascript', () async { + test('runJavaScriptForResult', () async { final String evaluateJavascript = - await webViewPlatform.evaluateJavascript( + await webViewPlatform.runJavaScriptForResult( 'This simulates some Javascript code.', ); @@ -309,7 +308,7 @@ void main() { log, [ isMethodCall( - 'evaluateJavascript', + 'runJavaScriptForResult', arguments: 'This simulates some Javascript code.', ), ], From 3a22d000a109dd191bb1141934e4477172680e00 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 1 Oct 2021 15:21:53 +0200 Subject: [PATCH 03/36] [webview_flutter] Implemented `runJavaScript` and `runJavaScriptForResult` in iOS and Android packages. --- .../webview_flutter_android/CHANGELOG.md | 4 + .../android/build.gradle | 4 + .../webviewflutter/FlutterWebView.java | 15 +- .../webviewflutter/FlutterWebViewTest.java | 109 +++++++- .../webview_flutter_test.dart | 52 ++-- .../example/lib/main.dart | 8 +- .../example/lib/web_view.dart | 32 ++- .../webview_flutter_android/pubspec.yaml | 6 +- .../webview_flutter_wkwebview/CHANGELOG.md | 4 + .../webview_flutter_test.dart | 43 ++- .../ios/Runner.xcodeproj/project.pbxproj | 9 + .../example/ios/RunnerTests/FLTWebViewTests.m | 246 ++++++++++++++++++ .../example/lib/main.dart | 8 +- .../example/lib/web_view.dart | 32 ++- .../ios/Classes/FlutterWebView.h | 20 +- .../ios/Classes/FlutterWebView.m | 54 +++- .../webview_flutter_wkwebview/pubspec.yaml | 6 +- 17 files changed, 556 insertions(+), 96 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index d4827a71e47d..4d84c1dd9df0 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Implemented new `runJavaScript` and `runJavaScriptForResult` methods in platform interface. + ## 2.0.15 * Added Overrides in FlutterWebView.java diff --git a/packages/webview_flutter/webview_flutter_android/android/build.gradle b/packages/webview_flutter/webview_flutter_android/android/build.gradle index 4a164317c60f..d7c70f4be648 100644 --- a/packages/webview_flutter/webview_flutter_android/android/build.gradle +++ b/packages/webview_flutter/webview_flutter_android/android/build.gradle @@ -54,4 +54,8 @@ android { } } } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index ff573c771960..7bb29ffbcb76 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -244,7 +244,11 @@ public void onMethodCall(MethodCall methodCall, Result result) { currentUrl(result); break; case "evaluateJavascript": - evaluateJavaScript(methodCall, result); + case "runJavaScriptForResult": + evaluateJavaScript(methodCall, result, true); + break; + case "runJavaScript": + evaluateJavaScript(methodCall, result, false); break; case "addJavascriptChannels": addJavaScriptChannels(methodCall, result); @@ -325,7 +329,8 @@ private void updateSettings(MethodCall methodCall, Result result) { } @TargetApi(Build.VERSION_CODES.KITKAT) - private void evaluateJavaScript(MethodCall methodCall, final Result result) { + private void evaluateJavaScript( + MethodCall methodCall, final Result result, final boolean returnValue) { String jsString = (String) methodCall.arguments; if (jsString == null) { throw new UnsupportedOperationException("JavaScript string cannot be null"); @@ -335,7 +340,11 @@ private void evaluateJavaScript(MethodCall methodCall, final Result result) { new android.webkit.ValueCallback() { @Override public void onReceiveValue(String value) { - result.success(value); + if (returnValue) { + result.success(value); + } else { + result.success(null); + } } }); } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java index 56d9db1ee493..8022aa39fdee 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java @@ -6,31 +6,46 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.content.Context; import android.webkit.DownloadListener; import android.webkit.WebChromeClient; import android.webkit.WebView; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; import java.util.HashMap; import java.util.Map; import org.junit.Before; import org.junit.Test; +import org.mockito.MockedStatic; public class FlutterWebViewTest { private WebChromeClient mockWebChromeClient; private DownloadListener mockDownloadListener; private WebViewBuilder mockWebViewBuilder; private WebView mockWebView; + private MethodChannel.Result mockResult; + private Context mockContext; + private MethodChannel mockMethodChannel; @Before public void before() { + mockWebChromeClient = mock(WebChromeClient.class); mockWebViewBuilder = mock(WebViewBuilder.class); mockWebView = mock(WebView.class); mockDownloadListener = mock(DownloadListener.class); + mockResult = mock(MethodChannel.Result.class); + mockContext = mock(Context.class); + mockMethodChannel = mock(MethodChannel.class); when(mockWebViewBuilder.setDomStorageEnabled(anyBoolean())).thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.setJavaScriptCanOpenWindowsAutomatically(anyBoolean())) @@ -41,12 +56,11 @@ public void before() { .thenReturn(mockWebViewBuilder); when(mockWebViewBuilder.setDownloadListener(any(DownloadListener.class))) .thenReturn(mockWebViewBuilder); - when(mockWebViewBuilder.build()).thenReturn(mockWebView); } @Test - public void createWebView_should_create_webview_with_default_configuration() { + public void createWebView_shouldCreateWebViewWithDefaultConfiguration() { FlutterWebView.createWebView( mockWebViewBuilder, createParameterMap(false), mockWebChromeClient, mockDownloadListener); @@ -57,6 +71,97 @@ public void createWebView_should_create_webview_with_default_configuration() { verify(mockWebViewBuilder, times(1)).setWebChromeClient(mockWebChromeClient); } + @Test(expected = UnsupportedOperationException.class) + public void evaluateJavaScript_shouldThrowForNullString() { + try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { + // Setup + mockedFlutterWebView + .when( + new MockedStatic.Verification() { + @Override + public void apply() throws Throwable { + FlutterWebView.createWebView( + (WebViewBuilder) any(), + (Map) any(), + (WebChromeClient) any(), + (DownloadListener) any()); + } + }) + .thenReturn(mockWebView); + FlutterWebView flutterWebView = + new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); + + // Run + flutterWebView.onMethodCall(new MethodCall("runJavaScript", null), mockResult); + } + } + + @Test + public void evaluateJavaScript_shouldReturnValueOnSuccessForReturnValue() { + try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { + // Setup + mockedFlutterWebView + .when( + () -> + FlutterWebView.createWebView( + (WebViewBuilder) any(), + (Map) any(), + (WebChromeClient) any(), + (DownloadListener) any())) + .thenReturn(mockWebView); + doAnswer( + invocation -> { + android.webkit.ValueCallback callback = invocation.getArgument(1); + callback.onReceiveValue("Test JavaScript Result"); + return null; + }) + .when(mockWebView) + .evaluateJavascript(eq("Test JavaScript String"), any()); + FlutterWebView flutterWebView = + new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); + + // Run + flutterWebView.onMethodCall( + new MethodCall("runJavaScriptForResult", "Test JavaScript String"), mockResult); + + // Verify + verify(mockResult, times(1)).success("Test JavaScript Result"); + } + } + + @Test + public void evaluateJavaScript_shouldReturnNilOnSuccessForNoReturnValue() { + try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { + // Setup + mockedFlutterWebView + .when( + () -> + FlutterWebView.createWebView( + (WebViewBuilder) any(), + (Map) any(), + (WebChromeClient) any(), + (DownloadListener) any())) + .thenReturn(mockWebView); + doAnswer( + invocation -> { + android.webkit.ValueCallback callback = invocation.getArgument(1); + callback.onReceiveValue("Test JavaScript Result"); + return null; + }) + .when(mockWebView) + .evaluateJavascript(eq("Test JavaScript String"), any()); + FlutterWebView flutterWebView = + new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); + + // Run + flutterWebView.onMethodCall( + new MethodCall("runJavaScript", "Test JavaScript String"), mockResult); + + // Verify + verify(mockResult, times(1)).success(isNull()); + } + } + private Map createParameterMap(boolean usesHybridComposition) { Map params = new HashMap<>(); params.put("usesHybridComposition", usesHybridComposition); diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index 3dab048c8ff2..8d57f09d6978 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -107,7 +107,7 @@ void main() { await pageLoads.stream.firstWhere((String url) => url == currentUrl); final String content = await controller - .evaluateJavascript('document.documentElement.innerText'); + .runJavaScriptForResult('document.documentElement.innerText'); expect(content.contains('flutter_test_header'), isTrue); }, skip: _skipDueToIssue86757); @@ -156,7 +156,7 @@ void main() { // See: https://github.com/flutter/flutter/issues/66318#issuecomment-701105380 // TODO(cyanglaz): remove the workaround "1" in the end when the below issue is fixed. // https://github.com/flutter/flutter/issues/66318 - await controller.evaluateJavascript('Echo.postMessage("hello");1;'); + await controller.runJavaScriptForResult('Echo.postMessage("hello");1;'); expect(messagesReceived, equals(['hello'])); }, skip: _skipDueToIssue86757); @@ -403,7 +403,7 @@ void main() { WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -432,7 +432,7 @@ void main() { controller = await controllerCompleter.future; await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -463,7 +463,7 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageLoaded = Completer(); @@ -491,7 +491,7 @@ void main() { await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); @@ -541,7 +541,7 @@ void main() { await videoPlaying.future; String fullScreen = - await controller.evaluateJavascript('isFullScreen();'); + await controller.runJavaScriptForResult('isFullScreen();'); expect(fullScreen, _webviewBool(false)); }); }); @@ -607,7 +607,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -641,7 +641,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -677,7 +677,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageStarted = Completer(); @@ -710,7 +710,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); }); @@ -975,14 +975,14 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - final String viewportRectJSON = await _evaluateJavascript( + final String viewportRectJSON = await _runJavaScriptForResult( controller, 'JSON.stringify(viewport.getBoundingClientRect())'); final Map viewportRectRelativeToViewport = jsonDecode(viewportRectJSON); // Check that the input is originally outside of the viewport. - final String initialInputClientRectJSON = await _evaluateJavascript( + final String initialInputClientRectJSON = await _runJavaScriptForResult( controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); final Map initialInputClientRectRelativeToViewport = jsonDecode(initialInputClientRectJSON); @@ -992,11 +992,11 @@ void main() { viewportRectRelativeToViewport['bottom'], isFalse); - await controller.evaluateJavascript('inputEl.focus()'); + await controller.runJavaScript('inputEl.focus()'); // Check that focusing the input brought it into view. - final String lastInputClientRectJSON = await _evaluateJavascript( + final String lastInputClientRectJSON = await _runJavaScriptForResult( controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); final Map lastInputClientRectRelativeToViewport = jsonDecode(lastInputClientRectJSON); @@ -1054,7 +1054,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('location.href = "https://www.example.com/"'); + .runJavaScript('location.href = "https://www.example.com/"'); await pageLoads.stream.first; // Wait for the next page load. final String? currentUrl = await controller.currentUrl(); @@ -1180,7 +1180,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('location.href = "https://www.youtube.com/"'); + .runJavaScript('location.href = "https://www.youtube.com/"'); // There should never be any second page load, since our new URL is // blocked. Still wait for a potential page change for some time in order @@ -1221,7 +1221,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('location.href = "https://www.example.com"'); + .runJavaScript('location.href = "https://www.example.com"'); await pageLoads.stream.first; // Wait for second page to load. final String? currentUrl = await controller.currentUrl(); @@ -1277,7 +1277,7 @@ void main() { ); final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('window.open("https://flutter.dev/", "_blank")'); + .runJavaScript('window.open("https://flutter.dev/", "_blank")'); await pageLoaded.future; final String? currentUrl = await controller.currentUrl(); expect(currentUrl, 'https://flutter.dev/'); @@ -1313,8 +1313,7 @@ void main() { await pageLoaded.future; pageLoaded = Completer(); - await controller - .evaluateJavascript('window.open("https://www.example.com/")'); + await controller.runJavaScript('window.open("https://www.example.com/")'); await pageLoaded.future; pageLoaded = Completer(); expect(controller.currentUrl(), completion('https://www.example.com/')); @@ -1385,9 +1384,10 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoadCompleter.future; - expect(controller.evaluateJavascript('iframeLoaded'), completion('true')); + expect(controller.runJavaScriptForResult('iframeLoaded'), + completion('true')); expect( - controller.evaluateJavascript( + controller.runJavaScriptForResult( 'document.querySelector("p") && document.querySelector("p").textContent'), completion('null'), ); @@ -1406,10 +1406,10 @@ String _webviewBool(bool value) { /// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests. Future _getUserAgent(WebViewController controller) async { - return _evaluateJavascript(controller, 'navigator.userAgent;'); + return _runJavaScriptForResult(controller, 'navigator.userAgent;'); } -Future _evaluateJavascript( +Future _runJavaScriptForResult( WebViewController controller, String js) async { - return jsonDecode(await controller.evaluateJavascript(js)); + return jsonDecode(await controller.runJavaScriptForResult(js)); } diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index 65f49716aaac..3b61377d26a6 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -195,14 +195,14 @@ class _SampleMenu extends StatelessWidget { WebViewController controller, BuildContext context) async { // Send a message with the user agent string to the Snackbar JavaScript channel we registered // with the WebView. - await controller.evaluateJavascript( + await controller.runJavaScript( 'Snackbar.postMessage("User Agent: " + navigator.userAgent);'); } void _onListCookies( WebViewController controller, BuildContext context) async { final String cookies = - await controller.evaluateJavascript('document.cookie'); + await controller.runJavaScriptForResult('document.cookie'); // ignore: deprecated_member_use Scaffold.of(context).showSnackBar(SnackBar( content: Column( @@ -217,7 +217,7 @@ class _SampleMenu extends StatelessWidget { } void _onAddToCache(WebViewController controller, BuildContext context) async { - await controller.evaluateJavascript( + await controller.runJavaScript( 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";'); // ignore: deprecated_member_use Scaffold.of(context).showSnackBar(const SnackBar( @@ -226,7 +226,7 @@ class _SampleMenu extends StatelessWidget { } void _onListCache(WebViewController controller, BuildContext context) async { - await controller.evaluateJavascript('caches.keys()' + await controller.runJavaScript('caches.keys()' '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' '.then((caches) => Snackbar.postMessage(caches))'); } diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart index 33773f96cad8..b6f84d86133e 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart @@ -481,31 +481,41 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } - /// Evaluates a JavaScript expression in the context of the current page. + /// Runs the given JavaScript in the context of the current page. + /// If you are looking for the result, use [runJavascriptForResult] instead. + /// The Future completes with an error if a JavaScript error occurred. + /// + /// When running Javascript in a [WebView], it is best practice to wait for + // the [WebView.onPageFinished] callback. This guarantees all the Javascript + // embedded in the main frame HTML has been loaded. + Future runJavaScript(String javaScriptString) { + if (_settings.javascriptMode == JavascriptMode.disabled) { + return Future.error(FlutterError( + 'JavaScript mode must be enabled/unrestricted when calling runJavaScript.')); + } + return _webViewPlatformController.runJavaScript(javaScriptString); + } + + /// Runs the given JavaScript in the context of the current page, and returns the result. /// /// On Android returns the evaluation result as a JSON formatted string. /// /// On iOS depending on the value type the return value would be one of: - /// /// - For primitive JavaScript types: the value string formatted (e.g JavaScript 100 returns '100'). /// - For JavaScript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). - /// - Other non-primitive types are not supported on iOS and will complete the Future with an error. + /// - Other non-primitive types are not supported on iOS and will return as null. /// - /// The Future completes with an error if a JavaScript error occurred, or on iOS, if the type of the - /// evaluated expression is not supported as described above. + /// The Future completes with an error if a JavaScript error occurred. /// /// When evaluating Javascript in a [WebView], it is best practice to wait for /// the [WebView.onPageFinished] callback. This guarantees all the Javascript /// embedded in the main frame HTML has been loaded. - Future evaluateJavascript(String javascriptString) { + Future runJavaScriptForResult(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { return Future.error(FlutterError( - 'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.')); + 'JavaScript mode must be enabled/unrestricted when calling runJavaScriptForResult.')); } - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - return _webViewPlatformController.evaluateJavascript(javascriptString); + return _webViewPlatformController.runJavaScriptForResult(javaScriptString); } /// Returns the title of the currently loaded page. diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 36f186087c08..76605aef3262 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 2.0.15 +version: 2.1.0 environment: sdk: ">=2.14.0 <3.0.0" @@ -20,7 +20,9 @@ dependencies: flutter: sdk: flutter - webview_flutter_platform_interface: ^1.0.0 + # TODO (BeMacized): Change to version dependency once interface is published + webview_flutter_platform_interface: + path: ../webview_flutter_platform_interface dev_dependencies: flutter_driver: diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 242d79b4bd82..f8fa3b4d7ecd 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Implemented new `runJavaScript` and `runJavaScriptForResult` methods in platform interface. + ## 2.0.14 * Update example App so navigation menu loads immediatly but only becomes available when `WebViewController` is available (same behavior as example App in webview_flutter package). diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index c080c46120ec..b81cf2ccf2d0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -103,7 +103,7 @@ void main() { await pageLoads.stream.firstWhere((String url) => url == currentUrl); final String content = await controller - .evaluateJavascript('document.documentElement.innerText'); + .runJavaScriptForResult('document.documentElement.innerText'); expect(content.contains('flutter_test_header'), isTrue); }); @@ -151,7 +151,7 @@ void main() { // See: https://github.com/flutter/flutter/issues/66318#issuecomment-701105380 // TODO(cyanglaz): remove the workaround "1" in the end when the below issue is fixed. // https://github.com/flutter/flutter/issues/66318 - await controller.evaluateJavascript('Echo.postMessage("hello");1;'); + await controller.runJavaScriptForResult('Echo.postMessage("hello");1;'); expect(messagesReceived, equals(['hello'])); }); @@ -397,7 +397,7 @@ void main() { WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -426,7 +426,7 @@ void main() { controller = await controllerCompleter.future; await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -457,7 +457,7 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageLoaded = Completer(); @@ -485,7 +485,7 @@ void main() { await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); @@ -535,7 +535,7 @@ void main() { await videoPlaying.future; String fullScreen = - await controller.evaluateJavascript('isFullScreen();'); + await controller.runJavaScriptForResult('isFullScreen();'); expect(fullScreen, _webviewBool(false)); }); @@ -586,7 +586,7 @@ void main() { await videoPlaying.future; String fullScreen = - await controller.evaluateJavascript('isFullScreen();'); + await controller.runJavaScriptForResult('isFullScreen();'); expect(fullScreen, _webviewBool(true)); }); }); @@ -652,7 +652,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -686,7 +686,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -722,7 +722,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.evaluateJavascript('isPaused();'); + String isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageStarted = Completer(); @@ -755,7 +755,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.evaluateJavascript('isPaused();'); + isPaused = await controller.runJavaScriptForResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); }); @@ -913,7 +913,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('location.href = "https://www.example.com/"'); + .runJavaScript('location.href = "https://www.example.com/"'); await pageLoads.stream.first; // Wait for the next page load. final String? currentUrl = await controller.currentUrl(); @@ -1044,7 +1044,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('location.href = "https://www.youtube.com/"'); + .runJavaScript('location.href = "https://www.youtube.com/"'); // There should never be any second page load, since our new URL is // blocked. Still wait for a potential page change for some time in order @@ -1085,7 +1085,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('location.href = "https://www.example.com"'); + .runJavaScript('location.href = "https://www.example.com"'); await pageLoads.stream.first; // Wait for second page to load. final String? currentUrl = await controller.currentUrl(); @@ -1141,7 +1141,7 @@ void main() { ); final WebViewController controller = await controllerCompleter.future; await controller - .evaluateJavascript('window.open("https://flutter.dev/", "_blank")'); + .runJavaScript('window.open("https://flutter.dev/", "_blank")'); await pageLoaded.future; final String? currentUrl = await controller.currentUrl(); expect(currentUrl, 'https://flutter.dev/'); @@ -1175,8 +1175,7 @@ void main() { await pageLoaded.future; pageLoaded = Completer(); - await controller - .evaluateJavascript('window.open("https://www.example.com/")'); + await controller.runJavaScript('window.open("https://www.example.com/")'); await pageLoaded.future; pageLoaded = Completer(); expect(controller.currentUrl(), completion('https://www.example.com/')); @@ -1201,13 +1200,13 @@ String _webviewBool(bool value) { /// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests. Future _getUserAgent(WebViewController controller) async { - return _evaluateJavascript(controller, 'navigator.userAgent;'); + return _runJavaScriptForResult(controller, 'navigator.userAgent;'); } -Future _evaluateJavascript( +Future _runJavaScriptForResult( WebViewController controller, String js) async { if (defaultTargetPlatform == TargetPlatform.iOS) { - return await controller.evaluateJavascript(js); + return await controller.runJavaScriptForResult(js); } - return jsonDecode(await controller.evaluateJavascript(js)); + return jsonDecode(await controller.runJavaScriptForResult(js)); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 62428d041adf..338b3e228980 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -277,13 +277,16 @@ ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 68BDCAE823C3F7CB00D9C032 = { + DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 7624MWN53C; }; F7151F73266057800028CB91 = { CreatedOnToolsVersion = 12.5; + DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; TestTargetID = 97C146ED1CF9000F007C117D; }; @@ -477,6 +480,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -491,6 +495,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -611,6 +616,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -634,6 +640,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -655,6 +662,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; @@ -668,6 +676,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m index 631c4a105063..3daeafa28a87 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m @@ -88,4 +88,250 @@ - (void)testContentInsetsSumAlwaysZeroAfterSetFrame { } } +- (void)testRunJavaScriptFailsForNullString { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return error result over the method channel."]; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" + arguments:nil] + result:^(id _Nullable result) { + XCTAssertTrue([result class] == [FlutterError class]); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptRunsStringWithSuccessResult { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return successful result over the method channel."]; + FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); + [OCMStub([mockView evaluateJavaScript:[OCMArg any] + completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { + // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 + __unsafe_unretained void (^evalResultHandler)(id, NSError *); + [invocation getArgument:&evalResultHandler atIndex:3]; + evalResultHandler(@"RESULT", nil); + }]; + controller.webView = mockView; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" + arguments:@"Test JavaScript String"] + result:^(id _Nullable result) { + XCTAssertNil(result); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptReturnsErrorResultForWKError { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return error result over the method channel."]; + NSError *testError = + [NSError errorWithDomain:@"" + // Any error code but WKErrorJavaScriptResultTypeIsUnsupported + code:WKErrorJavaScriptResultTypeIsUnsupported + 1 + userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; + FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); + [OCMStub([mockView evaluateJavaScript:[OCMArg any] + completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { + // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 + __unsafe_unretained void (^evalResultHandler)(id, NSError *); + [invocation getArgument:&evalResultHandler atIndex:3]; + evalResultHandler(nil, testError); + }]; + controller.webView = mockView; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" + arguments:@"Test JavaScript String"] + result:^(id _Nullable result) { + XCTAssertTrue([result class] == [FlutterError class]); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptReturnsSuccessForWKErrorJavaScriptResultTypeIsUnsupported { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return nil result over the method channel."]; + NSError *testError = [NSError errorWithDomain:@"" + code:WKErrorJavaScriptResultTypeIsUnsupported + userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; + FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); + [OCMStub([mockView evaluateJavaScript:[OCMArg any] + completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { + // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 + __unsafe_unretained void (^evalResultHandler)(id, NSError *); + [invocation getArgument:&evalResultHandler atIndex:3]; + evalResultHandler(nil, testError); + }]; + controller.webView = mockView; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" + arguments:@"Test JavaScript String"] + result:^(id _Nullable result) { + XCTAssertNil(result); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptForResultFailsForNullString { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return error result over the method channel."]; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" + arguments:nil] + result:^(id _Nullable result) { + XCTAssertTrue([result class] == [FlutterError class]); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptForResultRunsStringWithSuccessResult { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return successful result over the method channel."]; + FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); + [OCMStub([mockView evaluateJavaScript:[OCMArg any] + completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { + // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 + __unsafe_unretained void (^evalResultHandler)(id, NSError *); + [invocation getArgument:&evalResultHandler atIndex:3]; + evalResultHandler(@"RESULT", nil); + }]; + controller.webView = mockView; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" + arguments:@"Test JavaScript String"] + result:^(id _Nullable result) { + XCTAssertTrue([@"RESULT" isEqualToString:result]); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptForResultReturnsErrorResultForWKError { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return error result over the method channel."]; + NSError *testError = + [NSError errorWithDomain:@"" + // Any error code but WKErrorJavaScriptResultTypeIsUnsupported + code:WKErrorJavaScriptResultTypeIsUnsupported + 1 + userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; + FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); + [OCMStub([mockView evaluateJavaScript:[OCMArg any] + completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { + // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 + __unsafe_unretained void (^evalResultHandler)(id, NSError *); + [invocation getArgument:&evalResultHandler atIndex:3]; + evalResultHandler(nil, testError); + }]; + controller.webView = mockView; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" + arguments:@"Test JavaScript String"] + result:^(id _Nullable result) { + XCTAssertTrue([result class] == [FlutterError class]); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + +- (void)testRunJavaScriptForResultReturnsNilForWKErrorJavaScriptResultTypeIsUnsupported { + // Setup + FLTWebViewController *controller = + [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) + viewIdentifier:1 + arguments:nil + binaryMessenger:self.mockBinaryMessenger]; + XCTestExpectation *resultExpectation = + [self expectationWithDescription:@"Should return nil result over the method channel."]; + NSError *testError = [NSError errorWithDomain:@"" + code:WKErrorJavaScriptResultTypeIsUnsupported + userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; + FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); + [OCMStub([mockView evaluateJavaScript:[OCMArg any] + completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { + // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 + __unsafe_unretained void (^evalResultHandler)(id, NSError *); + [invocation getArgument:&evalResultHandler atIndex:3]; + evalResultHandler(nil, testError); + }]; + controller.webView = mockView; + + // Run + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" + arguments:@"Test JavaScript String"] + result:^(id _Nullable result) { + XCTAssertNil(result); + [resultExpectation fulfill]; + }]; + + // Verify + [self waitForExpectationsWithTimeout:30.0 handler:nil]; +} + @end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart index 15b4cfc7c549..b9aae2ae0d08 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart @@ -199,14 +199,14 @@ class _SampleMenu extends StatelessWidget { WebViewController controller, BuildContext context) async { // Send a message with the user agent string to the Snackbar JavaScript channel we registered // with the WebView. - await controller.evaluateJavascript( + await controller.runJavaScript( 'Snackbar.postMessage("User Agent: " + navigator.userAgent);'); } void _onListCookies( WebViewController controller, BuildContext context) async { final String cookies = - await controller.evaluateJavascript('document.cookie'); + await controller.runJavaScriptForResult('document.cookie'); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Column( mainAxisAlignment: MainAxisAlignment.end, @@ -220,7 +220,7 @@ class _SampleMenu extends StatelessWidget { } void _onAddToCache(WebViewController controller, BuildContext context) async { - await controller.evaluateJavascript( + await controller.runJavaScript( 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";'); ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text('Added a test entry to cache.'), @@ -228,7 +228,7 @@ class _SampleMenu extends StatelessWidget { } void _onListCache(WebViewController controller, BuildContext context) async { - await controller.evaluateJavascript('caches.keys()' + await controller.runJavaScript('caches.keys()' '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' '.then((caches) => Snackbar.postMessage(caches))'); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart index ddb8e9b0f14f..bfaeac0d25cd 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart @@ -410,31 +410,41 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } - /// Evaluates a JavaScript expression in the context of the current page. + /// Runs the given JavaScript in the context of the current page. + /// If you are looking for the result, use [runJavascriptForResult] instead. + /// The Future completes with an error if a JavaScript error occurred. + /// + /// When running Javascript in a [WebView], it is best practice to wait for + // the [WebView.onPageFinished] callback. This guarantees all the Javascript + // embedded in the main frame HTML has been loaded. + Future runJavaScript(String javaScriptString) { + if (_settings.javascriptMode == JavascriptMode.disabled) { + return Future.error(FlutterError( + 'JavaScript mode must be enabled/unrestricted when calling runJavaScript.')); + } + return _webViewPlatformController.runJavaScript(javaScriptString); + } + + /// Runs the given JavaScript in the context of the current page, and returns the result. /// /// On Android returns the evaluation result as a JSON formatted string. /// /// On iOS depending on the value type the return value would be one of: - /// /// - For primitive JavaScript types: the value string formatted (e.g JavaScript 100 returns '100'). /// - For JavaScript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). - /// - Other non-primitive types are not supported on iOS and will complete the Future with an error. + /// - Other non-primitive types are not supported on iOS and will return as null. /// - /// The Future completes with an error if a JavaScript error occurred, or on iOS, if the type of the - /// evaluated expression is not supported as described above. + /// The Future completes with an error if a JavaScript error occurred. /// /// When evaluating Javascript in a [WebView], it is best practice to wait for /// the [WebView.onPageFinished] callback. This guarantees all the Javascript /// embedded in the main frame HTML has been loaded. - Future evaluateJavascript(String javascriptString) { + Future runJavaScriptForResult(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { return Future.error(FlutterError( - 'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.')); + 'JavaScript mode must be enabled/unrestricted when calling runJavaScriptForResult.')); } - // TODO(amirh): remove this on when the invokeMethod update makes it to stable Flutter. - // https://github.com/flutter/flutter/issues/26431 - // ignore: strong_mode_implicit_dynamic_method - return _webViewPlatformController.evaluateJavascript(javascriptString); + return _webViewPlatformController.runJavaScriptForResult(javaScriptString); } /// Returns the title of the currently loaded page. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.h index 6e795f7d1528..db52124d6a7c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.h @@ -7,26 +7,30 @@ NS_ASSUME_NONNULL_BEGIN +/** + * The WkWebView used for the plugin. + * + * This class overrides some methods in `WKWebView` to serve the needs for the plugin. + */ +@interface FLTWKWebView : WKWebView +@end + @interface FLTWebViewController : NSObject +@property(nonatomic) FLTWKWebView* webView; + - (instancetype)initWithFrame:(CGRect)frame viewIdentifier:(int64_t)viewId arguments:(id _Nullable)args binaryMessenger:(NSObject*)messenger; - (UIView*)view; + +- (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result; @end @interface FLTWebViewFactory : NSObject - (instancetype)initWithMessenger:(NSObject*)messenger; @end -/** - * The WkWebView used for the plugin. - * - * This class overrides some methods in `WKWebView` to serve the needs for the plugin. - */ -@interface FLTWKWebView : WKWebView -@end - NS_ASSUME_NONNULL_END diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index c6d926d3cfc2..9bbfb4174603 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -151,6 +151,10 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { [self onCurrentUrl:call result:result]; } else if ([[call method] isEqualToString:@"evaluateJavascript"]) { [self onEvaluateJavaScript:call result:result]; + } else if ([[call method] isEqualToString:@"runJavaScript"]) { + [self onRunJavaScript:call result:result]; + } else if ([[call method] isEqualToString:@"runJavaScriptForResult"]) { + [self onRunJavaScriptForResult:call result:result]; } else if ([[call method] isEqualToString:@"addJavascriptChannels"]) { [self onAddJavaScriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"removeJavascriptChannels"]) { @@ -234,7 +238,7 @@ - (void)onEvaluateJavaScript:(FlutterMethodCall*)call result:(FlutterResult)resu completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error) { result([FlutterError - errorWithCode:@"evaluateJavaScript_failed" + errorWithCode:@"evaluateJavascript_failed" message:@"Failed evaluating JavaScript" details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", jsString, error]]); @@ -244,6 +248,54 @@ - (void)onEvaluateJavaScript:(FlutterMethodCall*)call result:(FlutterResult)resu }]; } +- (void)onRunJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result { + NSString* jsString = [call arguments]; + if (!jsString) { + result([FlutterError errorWithCode:@"runJavaScript_failed" + message:@"JavaScript String cannot be null" + details:nil]); + return; + } + [_webView evaluateJavaScript:jsString + completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { + if (error && error.code != WKErrorJavaScriptResultTypeIsUnsupported) { + result([FlutterError + errorWithCode:@"runJavaScript_failed" + message:@"Failed running JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + jsString, error]]); + } else { + result(nil); + } + }]; +} + +- (void)onRunJavaScriptForResult:(FlutterMethodCall*)call result:(FlutterResult)result { + NSString* jsString = [call arguments]; + if (!jsString) { + result([FlutterError errorWithCode:@"runJavaScriptForResult_failed" + message:@"JavaScript String cannot be null" + details:nil]); + return; + } + [_webView evaluateJavaScript:jsString + completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { + if (error) { + if (error.code != WKErrorJavaScriptResultTypeIsUnsupported) { + result([FlutterError + errorWithCode:@"runJavaScriptForResult_failed" + message:@"Failed running JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + jsString, error]]); + } else { + result(nil); + } + } else { + result([NSString stringWithFormat:@"%@", evaluateResult]); + } + }]; +} + - (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { NSArray* channelNames = [call arguments]; NSSet* channelNamesSet = [[NSSet alloc] initWithArray:channelNames]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index a7305cea7a94..e070845a1a0f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 2.0.14 +version: 2.1.0 environment: sdk: ">=2.14.0 <3.0.0" @@ -19,7 +19,9 @@ dependencies: flutter: sdk: flutter - webview_flutter_platform_interface: ^1.0.0 + # TODO (BeMacized): Change to version dependency once interface is published + webview_flutter_platform_interface: + path: ../webview_flutter_platform_interface dev_dependencies: flutter_driver: From 2bcec1cd27955a6dbe2151e2bf7480e77cd72774 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 1 Oct 2021 15:25:29 +0200 Subject: [PATCH 04/36] Remove accidental development team inclusion from project.pbxproj --- .../example/ios/Runner.xcodeproj/project.pbxproj | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 338b3e228980..62428d041adf 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -277,16 +277,13 @@ ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 68BDCAE823C3F7CB00D9C032 = { - DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = 7624MWN53C; }; F7151F73266057800028CB91 = { CreatedOnToolsVersion = 12.5; - DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; TestTargetID = 97C146ED1CF9000F007C117D; }; @@ -480,7 +477,6 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -495,7 +491,6 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -616,7 +611,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -640,7 +634,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -662,7 +655,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; @@ -676,7 +668,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; From ff493a27cf53cd391a352e0a1a640d46b5e09d29 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 1 Oct 2021 15:38:55 +0200 Subject: [PATCH 05/36] Implemented PR feedback --- .../src/platform_interface/webview_platform_controller.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart index 6ccba8b63fb0..c7f433b5d0c9 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart @@ -122,8 +122,8 @@ abstract class WebViewPlatformController { /// Runs the given JavaScript in the context of the current page, and returns the result. /// - /// The Future completes with an error if a JavaScript error occurred, or successfully completes with a null value - /// if the type of the value is not supported(e.g on iOS not all non primitive type can be evaluated). + /// The Future completes with an error if a JavaScript error occurred, or if the type of the + /// evaluated expression is not supported(e.g on iOS not all non primitive type can be evaluated). Future runJavaScriptForResult(String javaScriptString) { throw UnimplementedError( "WebView runJavaScriptForResult is not implemented on the current platform"); From ff125c988130c2820736ce4df0f714308642fb35 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 1 Oct 2021 15:42:40 +0200 Subject: [PATCH 06/36] Updated runJavaScriptForResult behaviour --- .../example/ios/RunnerTests/FLTWebViewTests.m | 40 +------------------ .../ios/Classes/FlutterWebView.m | 14 +++---- 2 files changed, 7 insertions(+), 47 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m index 3daeafa28a87..5d3d9e71e747 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m @@ -273,44 +273,8 @@ - (void)testRunJavaScriptForResultReturnsErrorResultForWKError { binaryMessenger:self.mockBinaryMessenger]; XCTestExpectation *resultExpectation = [self expectationWithDescription:@"Should return error result over the method channel."]; - NSError *testError = - [NSError errorWithDomain:@"" - // Any error code but WKErrorJavaScriptResultTypeIsUnsupported - code:WKErrorJavaScriptResultTypeIsUnsupported + 1 - userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; - FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); - [OCMStub([mockView evaluateJavaScript:[OCMArg any] - completionHandler:[OCMArg any]]) andDo:^(NSInvocation *invocation) { - // __unsafe_unretained: https://github.com/erikdoe/ocmock/issues/384#issuecomment-589376668 - __unsafe_unretained void (^evalResultHandler)(id, NSError *); - [invocation getArgument:&evalResultHandler atIndex:3]; - evalResultHandler(nil, testError); - }]; - controller.webView = mockView; - - // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" - arguments:@"Test JavaScript String"] - result:^(id _Nullable result) { - XCTAssertTrue([result class] == [FlutterError class]); - [resultExpectation fulfill]; - }]; - - // Verify - [self waitForExpectationsWithTimeout:30.0 handler:nil]; -} - -- (void)testRunJavaScriptForResultReturnsNilForWKErrorJavaScriptResultTypeIsUnsupported { - // Setup - FLTWebViewController *controller = - [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) - viewIdentifier:1 - arguments:nil - binaryMessenger:self.mockBinaryMessenger]; - XCTestExpectation *resultExpectation = - [self expectationWithDescription:@"Should return nil result over the method channel."]; NSError *testError = [NSError errorWithDomain:@"" - code:WKErrorJavaScriptResultTypeIsUnsupported + code:5 userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); [OCMStub([mockView evaluateJavaScript:[OCMArg any] @@ -326,7 +290,7 @@ - (void)testRunJavaScriptForResultReturnsNilForWKErrorJavaScriptResultTypeIsUnsu [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" arguments:@"Test JavaScript String"] result:^(id _Nullable result) { - XCTAssertNil(result); + XCTAssertTrue([result class] == [FlutterError class]); [resultExpectation fulfill]; }]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 9bbfb4174603..7e28cd9c0b70 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -281,15 +281,11 @@ - (void)onRunJavaScriptForResult:(FlutterMethodCall*)call result:(FlutterResult) [_webView evaluateJavaScript:jsString completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error) { - if (error.code != WKErrorJavaScriptResultTypeIsUnsupported) { - result([FlutterError - errorWithCode:@"runJavaScriptForResult_failed" - message:@"Failed running JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", - jsString, error]]); - } else { - result(nil); - } + result([FlutterError + errorWithCode:@"runJavaScriptForResult_failed" + message:@"Failed running JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + jsString, error]]); } else { result([NSString stringWithFormat:@"%@", evaluateResult]); } From 9f661e87565a288dd67a4626ca349f9efb498ec2 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Mon, 4 Oct 2021 12:34:59 +0200 Subject: [PATCH 07/36] Implemented PR feedback partially --- .../webview_platform_controller.dart | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart index c7f433b5d0c9..64516420afa3 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart @@ -106,8 +106,8 @@ abstract class WebViewPlatformController { /// Evaluates a JavaScript expression in the context of the current page. /// /// The Future completes with an error if a JavaScript error occurred, or if the type of the - /// evaluated expression is not supported(e.g on iOS not all non primitive type can be evaluated). - Future evaluateJavascript(String javascriptString) { + /// evaluated expression is not supported (e.g on iOS not all non primitive types can be evaluated). + Future evaluateJavascript(String javaScript) { throw UnimplementedError( "WebView evaluateJavascript is not implemented on the current platform"); } @@ -115,16 +115,17 @@ abstract class WebViewPlatformController { /// Runs the given JavaScript in the context of the current page. /// /// The Future completes with an error if a JavaScript error occurred. - Future runJavaScript(String javaScriptString) { + Future runJavaScript(String javaScript) { throw UnimplementedError( "WebView runJavaScript is not implemented on the current platform"); } /// Runs the given JavaScript in the context of the current page, and returns the result. /// - /// The Future completes with an error if a JavaScript error occurred, or if the type of the - /// evaluated expression is not supported(e.g on iOS not all non primitive type can be evaluated). - Future runJavaScriptForResult(String javaScriptString) { + /// The Future completes with an error if a JavaScript error occurred, or if the + /// type the given expression evaluates to is unsupported. Unsupported values include + /// certain non primitive types on iOS, as well as `undefined` or `null` on iOS 14+. + Future runJavaScriptForResult(String javaScript) { throw UnimplementedError( "WebView runJavaScriptForResult is not implemented on the current platform"); } From cbc88e8ecc3dff6a409b976a293b8b7b9b70bb54 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Mon, 4 Oct 2021 13:55:54 +0200 Subject: [PATCH 08/36] Implement PR feedback --- .../webview_method_channel.dart | 12 +++---- .../webview_platform_controller.dart | 32 +++++++++---------- .../webview_method_channel_test.dart | 14 ++++---- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart index 29cb1bdde798..09f98fae216a 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/method_channel/webview_method_channel.dart @@ -123,21 +123,21 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController { } @override - Future evaluateJavascript(String javascriptString) { + Future evaluateJavascript(String javascript) { return _channel - .invokeMethod('evaluateJavascript', javascriptString) + .invokeMethod('evaluateJavascript', javascript) .then((result) => result!); } @override - Future runJavaScript(String javaScriptString) async { - await _channel.invokeMethod('runJavaScript', javaScriptString); + Future runJavascript(String javascript) async { + await _channel.invokeMethod('runJavascript', javascript); } @override - Future runJavaScriptForResult(String javaScriptString) { + Future runJavascriptReturningResult(String javascript) { return _channel - .invokeMethod('runJavaScriptForResult', javaScriptString) + .invokeMethod('runJavascriptReturningResult', javascript) .then((result) => result!); } diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart index 64516420afa3..ea0469706128 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart @@ -103,38 +103,38 @@ abstract class WebViewPlatformController { "WebView clearCache is not implemented on the current platform"); } - /// Evaluates a JavaScript expression in the context of the current page. + /// Evaluates a Javascript expression in the context of the current page. /// - /// The Future completes with an error if a JavaScript error occurred, or if the type of the + /// The Future completes with an error if a Javascript error occurred, or if the type of the /// evaluated expression is not supported (e.g on iOS not all non primitive types can be evaluated). - Future evaluateJavascript(String javaScript) { + Future evaluateJavascript(String javascript) { throw UnimplementedError( "WebView evaluateJavascript is not implemented on the current platform"); } - /// Runs the given JavaScript in the context of the current page. + /// Runs the given Javascript in the context of the current page. /// - /// The Future completes with an error if a JavaScript error occurred. - Future runJavaScript(String javaScript) { + /// The Future completes with an error if a Javascript error occurred. + Future runJavascript(String javascript) { throw UnimplementedError( - "WebView runJavaScript is not implemented on the current platform"); + "WebView runJavascript is not implemented on the current platform"); } - /// Runs the given JavaScript in the context of the current page, and returns the result. + /// Runs the given Javascript in the context of the current page, and returns the result. /// - /// The Future completes with an error if a JavaScript error occurred, or if the + /// The Future completes with an error if a Javascript error occurred, or if the /// type the given expression evaluates to is unsupported. Unsupported values include /// certain non primitive types on iOS, as well as `undefined` or `null` on iOS 14+. - Future runJavaScriptForResult(String javaScript) { + Future runJavascriptReturningResult(String javascript) { throw UnimplementedError( - "WebView runJavaScriptForResult is not implemented on the current platform"); + "WebView runJavascriptReturningResult is not implemented on the current platform"); } - /// Adds new JavaScript channels to the set of enabled channels. + /// Adds new Javascript channels to the set of enabled channels. /// /// For each value in this list the platform's webview should make sure that a corresponding - /// property with a postMessage method is set on `window`. For example for a JavaScript channel - /// named `Foo` it should be possible for JavaScript code executing in the webview to do + /// property with a postMessage method is set on `window`. For example for a Javascript channel + /// named `Foo` it should be possible for Javascript code executing in the webview to do /// /// ```javascript /// Foo.postMessage('hello'); @@ -146,9 +146,9 @@ abstract class WebViewPlatformController { "WebView addJavascriptChannels is not implemented on the current platform"); } - /// Removes JavaScript channel names from the set of enabled channels. + /// Removes Javascript channel names from the set of enabled channels. /// - /// This disables channels that were previously enabled by [addJavaScriptChannels] or through + /// This disables channels that were previously enabled by [addJavascriptChannels] or through /// [CreationParams.javascriptChannelNames]. Future removeJavascriptChannels(Set javascriptChannelNames) { throw UnimplementedError( diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart index 358eaf9aa396..1eee15547908 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart @@ -31,7 +31,7 @@ void main() { case 'canGoBack': case 'canGoForward': return true; - case 'runJavaScriptForResult': + case 'runJavascriptReturningResult': case 'evaluateJavascript': return methodCall.arguments as String; case 'getScrollX': @@ -281,8 +281,8 @@ void main() { ); }); - test('runJavaScript', () async { - await webViewPlatform.runJavaScript( + test('runJavascript', () async { + await webViewPlatform.runJavascript( 'This simulates some Javascript code.', ); @@ -290,16 +290,16 @@ void main() { log, [ isMethodCall( - 'runJavaScript', + 'runJavascript', arguments: 'This simulates some Javascript code.', ), ], ); }); - test('runJavaScriptForResult', () async { + test('runJavascriptReturningResult', () async { final String evaluateJavascript = - await webViewPlatform.runJavaScriptForResult( + await webViewPlatform.runJavascriptReturningResult( 'This simulates some Javascript code.', ); @@ -308,7 +308,7 @@ void main() { log, [ isMethodCall( - 'runJavaScriptForResult', + 'runJavascriptReturningResult', arguments: 'This simulates some Javascript code.', ), ], From 26004c3c09d9447476bbf42117f3ee207c642d04 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Mon, 4 Oct 2021 14:00:11 +0200 Subject: [PATCH 09/36] Update changelog --- .../webview_flutter_platform_interface/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index 5a37994f4fa3..d15755699a79 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.1.0 -* Added `runJavaScript` and `runJavaScriptForResult` interface methods to supersede `evaluateJavaScript`. +* Added `runJavascript` and `runJavascriptReturningResult` interface methods to supersede `evaluateJavaScript`. ## 1.0.0 From b95d986d4acee379c6ceb2a10b2fe0188255a43c Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Mon, 4 Oct 2021 15:11:10 +0200 Subject: [PATCH 10/36] Implement PR feedback from interface PR --- .../webview_flutter_android/CHANGELOG.md | 2 +- .../webviewflutter/FlutterWebView.java | 32 +++---- .../webviewflutter/JavaScriptChannel.java | 14 ++-- .../webviewflutter/FlutterWebViewTest.java | 22 ++--- .../webview_flutter_test.dart | 68 +++++++-------- .../example/lib/main.dart | 10 +-- .../example/lib/web_view.dart | 37 ++++---- .../webview_flutter_test.dart | 51 ++++++----- .../ios/Runner.xcodeproj/project.pbxproj | 9 ++ .../example/ios/RunnerTests/FLTWebViewTests.m | 69 +++++++-------- .../example/lib/main.dart | 10 +-- .../example/lib/web_view.dart | 41 ++++----- .../ios/Classes/FlutterWebView.m | 84 +++++++++---------- ...elHandler.h => JavascriptChannelHandler.h} | 4 +- ...elHandler.m => JavascriptChannelHandler.m} | 20 ++--- 15 files changed, 247 insertions(+), 226 deletions(-) rename packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/{JavaScriptChannelHandler.h => JavascriptChannelHandler.h} (73%) rename packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/{JavaScriptChannelHandler.m => JavascriptChannelHandler.m} (65%) diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index 4d84c1dd9df0..25f136b0b2b0 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.1.0 -* Implemented new `runJavaScript` and `runJavaScriptForResult` methods in platform interface. +* Implemented new `runJavascript` and `runJavascriptReturningResult` methods in platform interface. ## 2.0.15 diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index 7bb29ffbcb76..1b79012148ee 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -123,7 +123,7 @@ public void onProgressChanged(WebView view, int progress) { if (params.containsKey(JS_CHANNEL_NAMES_FIELD)) { List names = (List) params.get(JS_CHANNEL_NAMES_FIELD); if (names != null) { - registerJavaScriptChannelNames(names); + registerJavascriptChannelNames(names); } } @@ -149,7 +149,7 @@ public void onProgressChanged(WebView view, int progress) { * *
    *
  • always enable the DOM storage API; - *
  • always allow JavaScript to automatically open windows; + *
  • always allow Javascript to automatically open windows; *
  • always allow support for multiple windows; *
  • always use the {@link FlutterWebChromeClient} as web Chrome client. *
@@ -244,17 +244,17 @@ public void onMethodCall(MethodCall methodCall, Result result) { currentUrl(result); break; case "evaluateJavascript": - case "runJavaScriptForResult": - evaluateJavaScript(methodCall, result, true); + case "runJavascriptReturningResult": + evaluateJavascript(methodCall, result, true); break; - case "runJavaScript": - evaluateJavaScript(methodCall, result, false); + case "runJavascript": + evaluateJavascript(methodCall, result, false); break; case "addJavascriptChannels": - addJavaScriptChannels(methodCall, result); + addJavascriptChannels(methodCall, result); break; case "removeJavascriptChannels": - removeJavaScriptChannels(methodCall, result); + removeJavascriptChannels(methodCall, result); break; case "clearCache": clearCache(result); @@ -329,11 +329,11 @@ private void updateSettings(MethodCall methodCall, Result result) { } @TargetApi(Build.VERSION_CODES.KITKAT) - private void evaluateJavaScript( + private void evaluateJavascript( MethodCall methodCall, final Result result, final boolean returnValue) { String jsString = (String) methodCall.arguments; if (jsString == null) { - throw new UnsupportedOperationException("JavaScript string cannot be null"); + throw new UnsupportedOperationException("Javascript string cannot be null"); } webView.evaluateJavascript( jsString, @@ -350,14 +350,14 @@ public void onReceiveValue(String value) { } @SuppressWarnings("unchecked") - private void addJavaScriptChannels(MethodCall methodCall, Result result) { + private void addJavascriptChannels(MethodCall methodCall, Result result) { List channelNames = (List) methodCall.arguments; - registerJavaScriptChannelNames(channelNames); + registerJavascriptChannelNames(channelNames); result.success(null); } @SuppressWarnings("unchecked") - private void removeJavaScriptChannels(MethodCall methodCall, Result result) { + private void removeJavascriptChannels(MethodCall methodCall, Result result) { List channelNames = (List) methodCall.arguments; for (String channelName : channelNames) { webView.removeJavascriptInterface(channelName); @@ -452,7 +452,7 @@ private void updateJsMode(int mode) { webView.getSettings().setJavaScriptEnabled(true); break; default: - throw new IllegalArgumentException("Trying to set unknown JavaScript mode: " + mode); + throw new IllegalArgumentException("Trying to set unknown Javascript mode: " + mode); } } @@ -465,10 +465,10 @@ private void updateAutoMediaPlaybackPolicy(int mode) { } } - private void registerJavaScriptChannelNames(List channelNames) { + private void registerJavascriptChannelNames(List channelNames) { for (String channelName : channelNames) { webView.addJavascriptInterface( - new JavaScriptChannel(methodChannel, channelName, platformThreadHandler), channelName); + new JavascriptChannel(methodChannel, channelName, platformThreadHandler), channelName); } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java index 4d596351b3d0..918d7cc42a20 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java @@ -17,21 +17,21 @@ *

Exposes a single method named `postMessage` to JavaScript, which sends a message over a method * channel to the Dart code. */ -class JavaScriptChannel { +class JavascriptChannel { private final MethodChannel methodChannel; - private final String javaScriptChannelName; + private final String javascriptChannelName; private final Handler platformThreadHandler; /** * @param methodChannel the Flutter WebView method channel to which JS messages are sent - * @param javaScriptChannelName the name of the JavaScript channel, this is sent over the method + * @param javascriptChannelName the name of the JavaScript channel, this is sent over the method * channel with each message to let the Dart code know which JavaScript channel the message * was sent through */ - JavaScriptChannel( - MethodChannel methodChannel, String javaScriptChannelName, Handler platformThreadHandler) { + JavascriptChannel( + MethodChannel methodChannel, String javascriptChannelName, Handler platformThreadHandler) { this.methodChannel = methodChannel; - this.javaScriptChannelName = javaScriptChannelName; + this.javascriptChannelName = javascriptChannelName; this.platformThreadHandler = platformThreadHandler; } @@ -44,7 +44,7 @@ public void postMessage(final String message) { @Override public void run() { HashMap arguments = new HashMap<>(); - arguments.put("channel", javaScriptChannelName); + arguments.put("channel", javascriptChannelName); arguments.put("message", message); methodChannel.invokeMethod("javascriptChannelMessage", arguments); } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java index 8022aa39fdee..705c46ea5130 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java @@ -72,7 +72,7 @@ public void createWebView_shouldCreateWebViewWithDefaultConfiguration() { } @Test(expected = UnsupportedOperationException.class) - public void evaluateJavaScript_shouldThrowForNullString() { + public void evaluateJavascript_shouldThrowForNullString() { try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { // Setup mockedFlutterWebView @@ -92,12 +92,12 @@ public void apply() throws Throwable { new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); // Run - flutterWebView.onMethodCall(new MethodCall("runJavaScript", null), mockResult); + flutterWebView.onMethodCall(new MethodCall("runJavascript", null), mockResult); } } @Test - public void evaluateJavaScript_shouldReturnValueOnSuccessForReturnValue() { + public void evaluateJavascript_shouldReturnValueOnSuccessForReturnValue() { try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { // Setup mockedFlutterWebView @@ -112,25 +112,25 @@ public void evaluateJavaScript_shouldReturnValueOnSuccessForReturnValue() { doAnswer( invocation -> { android.webkit.ValueCallback callback = invocation.getArgument(1); - callback.onReceiveValue("Test JavaScript Result"); + callback.onReceiveValue("Test Javascript Result"); return null; }) .when(mockWebView) - .evaluateJavascript(eq("Test JavaScript String"), any()); + .evaluateJavascript(eq("Test Javascript String"), any()); FlutterWebView flutterWebView = new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); // Run flutterWebView.onMethodCall( - new MethodCall("runJavaScriptForResult", "Test JavaScript String"), mockResult); + new MethodCall("runJavascriptReturningResult", "Test Javascript String"), mockResult); // Verify - verify(mockResult, times(1)).success("Test JavaScript Result"); + verify(mockResult, times(1)).success("Test Javascript Result"); } } @Test - public void evaluateJavaScript_shouldReturnNilOnSuccessForNoReturnValue() { + public void evaluateJavascript_shouldReturnNilOnSuccessForNoReturnValue() { try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { // Setup mockedFlutterWebView @@ -145,17 +145,17 @@ public void evaluateJavaScript_shouldReturnNilOnSuccessForNoReturnValue() { doAnswer( invocation -> { android.webkit.ValueCallback callback = invocation.getArgument(1); - callback.onReceiveValue("Test JavaScript Result"); + callback.onReceiveValue("Test Javascript Result"); return null; }) .when(mockWebView) - .evaluateJavascript(eq("Test JavaScript String"), any()); + .evaluateJavascript(eq("Test Javascript String"), any()); FlutterWebView flutterWebView = new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); // Run flutterWebView.onMethodCall( - new MethodCall("runJavaScript", "Test JavaScript String"), mockResult); + new MethodCall("runJavascript", "Test Javascript String"), mockResult); // Verify verify(mockResult, times(1)).success(isNull()); diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index 8d57f09d6978..d90df56fa875 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -107,12 +107,12 @@ void main() { await pageLoads.stream.firstWhere((String url) => url == currentUrl); final String content = await controller - .runJavaScriptForResult('document.documentElement.innerText'); + .runJavascriptReturningResult('document.documentElement.innerText'); expect(content.contains('flutter_test_header'), isTrue); }, skip: _skipDueToIssue86757); // TODO(bparrishMines): skipped due to https://github.com/flutter/flutter/issues/86757. - testWidgets('JavaScriptChannel', (WidgetTester tester) async { + testWidgets('JavascriptChannel', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); final Completer pageStarted = Completer(); @@ -152,11 +152,7 @@ void main() { await pageLoaded.future; expect(messagesReceived, isEmpty); - // Append a return value "1" in the end will prevent an iOS platform exception. - // See: https://github.com/flutter/flutter/issues/66318#issuecomment-701105380 - // TODO(cyanglaz): remove the workaround "1" in the end when the below issue is fixed. - // https://github.com/flutter/flutter/issues/66318 - await controller.runJavaScriptForResult('Echo.postMessage("hello");1;'); + await controller.runJavascript('Echo.postMessage("hello");'); expect(messagesReceived, equals(['hello'])); }, skip: _skipDueToIssue86757); @@ -403,7 +399,8 @@ void main() { WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -432,7 +429,7 @@ void main() { controller = await controllerCompleter.future; await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -463,7 +460,8 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageLoaded = Completer(); @@ -491,7 +489,7 @@ void main() { await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); @@ -541,7 +539,7 @@ void main() { await videoPlaying.future; String fullScreen = - await controller.runJavaScriptForResult('isFullScreen();'); + await controller.runJavascriptReturningResult('isFullScreen();'); expect(fullScreen, _webviewBool(false)); }); }); @@ -607,7 +605,8 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -641,7 +640,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -677,7 +676,8 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageStarted = Completer(); @@ -710,7 +710,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); }); @@ -975,15 +975,16 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - final String viewportRectJSON = await _runJavaScriptForResult( + final String viewportRectJSON = await _runJavascriptReturningResult( controller, 'JSON.stringify(viewport.getBoundingClientRect())'); final Map viewportRectRelativeToViewport = jsonDecode(viewportRectJSON); // Check that the input is originally outside of the viewport. - final String initialInputClientRectJSON = await _runJavaScriptForResult( - controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); + final String initialInputClientRectJSON = + await _runJavascriptReturningResult( + controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); final Map initialInputClientRectRelativeToViewport = jsonDecode(initialInputClientRectJSON); @@ -992,12 +993,13 @@ void main() { viewportRectRelativeToViewport['bottom'], isFalse); - await controller.runJavaScript('inputEl.focus()'); + await controller.runJavascript('inputEl.focus()'); // Check that focusing the input brought it into view. - final String lastInputClientRectJSON = await _runJavaScriptForResult( - controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); + final String lastInputClientRectJSON = + await _runJavascriptReturningResult( + controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); final Map lastInputClientRectRelativeToViewport = jsonDecode(lastInputClientRectJSON); @@ -1054,7 +1056,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('location.href = "https://www.example.com/"'); + .runJavascript('location.href = "https://www.example.com/"'); await pageLoads.stream.first; // Wait for the next page load. final String? currentUrl = await controller.currentUrl(); @@ -1180,7 +1182,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('location.href = "https://www.youtube.com/"'); + .runJavascript('location.href = "https://www.youtube.com/"'); // There should never be any second page load, since our new URL is // blocked. Still wait for a potential page change for some time in order @@ -1221,7 +1223,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('location.href = "https://www.example.com"'); + .runJavascript('location.href = "https://www.example.com"'); await pageLoads.stream.first; // Wait for second page to load. final String? currentUrl = await controller.currentUrl(); @@ -1277,7 +1279,7 @@ void main() { ); final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('window.open("https://flutter.dev/", "_blank")'); + .runJavascript('window.open("https://flutter.dev/", "_blank")'); await pageLoaded.future; final String? currentUrl = await controller.currentUrl(); expect(currentUrl, 'https://flutter.dev/'); @@ -1313,7 +1315,7 @@ void main() { await pageLoaded.future; pageLoaded = Completer(); - await controller.runJavaScript('window.open("https://www.example.com/")'); + await controller.runJavascript('window.open("https://www.example.com/")'); await pageLoaded.future; pageLoaded = Completer(); expect(controller.currentUrl(), completion('https://www.example.com/')); @@ -1384,10 +1386,10 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoadCompleter.future; - expect(controller.runJavaScriptForResult('iframeLoaded'), + expect(controller.runJavascriptReturningResult('iframeLoaded'), completion('true')); expect( - controller.runJavaScriptForResult( + controller.runJavascriptReturningResult( 'document.querySelector("p") && document.querySelector("p").textContent'), completion('null'), ); @@ -1395,7 +1397,7 @@ void main() { ); } -// JavaScript booleans evaluate to different string values on Android and iOS. +// Javascript booleans evaluate to different string values on Android and iOS. // This utility method returns the string boolean value of the current platform. String _webviewBool(bool value) { if (defaultTargetPlatform == TargetPlatform.iOS) { @@ -1406,10 +1408,10 @@ String _webviewBool(bool value) { /// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests. Future _getUserAgent(WebViewController controller) async { - return _runJavaScriptForResult(controller, 'navigator.userAgent;'); + return _runJavascriptReturningResult(controller, 'navigator.userAgent;'); } -Future _runJavaScriptForResult( +Future _runJavascriptReturningResult( WebViewController controller, String js) async { - return jsonDecode(await controller.runJavaScriptForResult(js)); + return jsonDecode(await controller.runJavascriptReturningResult(js)); } diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index 3b61377d26a6..091ee94b2771 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -193,16 +193,16 @@ class _SampleMenu extends StatelessWidget { void _onShowUserAgent( WebViewController controller, BuildContext context) async { - // Send a message with the user agent string to the Snackbar JavaScript channel we registered + // Send a message with the user agent string to the Snackbar Javascript channel we registered // with the WebView. - await controller.runJavaScript( + await controller.runJavascript( 'Snackbar.postMessage("User Agent: " + navigator.userAgent);'); } void _onListCookies( WebViewController controller, BuildContext context) async { final String cookies = - await controller.runJavaScriptForResult('document.cookie'); + await controller.runJavascriptReturningResult('document.cookie'); // ignore: deprecated_member_use Scaffold.of(context).showSnackBar(SnackBar( content: Column( @@ -217,7 +217,7 @@ class _SampleMenu extends StatelessWidget { } void _onAddToCache(WebViewController controller, BuildContext context) async { - await controller.runJavaScript( + await controller.runJavascript( 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";'); // ignore: deprecated_member_use Scaffold.of(context).showSnackBar(const SnackBar( @@ -226,7 +226,7 @@ class _SampleMenu extends StatelessWidget { } void _onListCache(WebViewController controller, BuildContext context) async { - await controller.runJavaScript('caches.keys()' + await controller.runJavascript('caches.keys()' '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' '.then((caches) => Snackbar.postMessage(caches))'); } diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart index b6f84d86133e..63d69483fb03 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart @@ -118,11 +118,11 @@ class WebView extends StatefulWidget { /// Whether Javascript execution is enabled. final JavascriptMode javascriptMode; - /// The set of [JavascriptChannel]s available to JavaScript code running in the web view. + /// The set of [JavascriptChannel]s available to Javascript code running in the web view. /// /// For each [JavascriptChannel] in the set, a channel object is made available for the - /// JavaScript code in a window property named [JavascriptChannel.name]. - /// The JavaScript code can then call `postMessage` on that object to send a message that will be + /// Javascript code in a window property named [JavascriptChannel.name]. + /// The Javascript code can then call `postMessage` on that object to send a message that will be /// passed to [JavascriptChannel.onMessageReceived]. /// /// For example for the following JavascriptChannel: @@ -131,7 +131,7 @@ class WebView extends StatefulWidget { /// JavascriptChannel(name: 'Print', onMessageReceived: (JavascriptMessage message) { print(message.message); }); /// ``` /// - /// JavaScript code can call: + /// Javascript code can call: /// /// ```javascript /// Print.postMessage('Hello'); @@ -139,7 +139,7 @@ class WebView extends StatefulWidget { /// /// To asynchronously invoke the message handler which will print the message to standard output. /// - /// Adding a new JavaScript channel only takes affect after the next page is loaded. + /// Adding a new Javascript channel only takes affect after the next page is loaded. /// /// Set values must not be null. A [JavascriptChannel.name] cannot be the same for multiple /// channels in the list. @@ -481,41 +481,42 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } - /// Runs the given JavaScript in the context of the current page. - /// If you are looking for the result, use [runJavascriptForResult] instead. - /// The Future completes with an error if a JavaScript error occurred. + /// Runs the given Javascript in the context of the current page. + /// If you are looking for the result, use [runJavascriptReturningResult] instead. + /// The Future completes with an error if a Javascript error occurred. /// /// When running Javascript in a [WebView], it is best practice to wait for // the [WebView.onPageFinished] callback. This guarantees all the Javascript // embedded in the main frame HTML has been loaded. - Future runJavaScript(String javaScriptString) { + Future runJavascript(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { return Future.error(FlutterError( - 'JavaScript mode must be enabled/unrestricted when calling runJavaScript.')); + 'Javascript mode must be enabled/unrestricted when calling runJavascript.')); } - return _webViewPlatformController.runJavaScript(javaScriptString); + return _webViewPlatformController.runJavascript(javaScriptString); } - /// Runs the given JavaScript in the context of the current page, and returns the result. + /// Runs the given Javascript in the context of the current page, and returns the result. /// /// On Android returns the evaluation result as a JSON formatted string. /// /// On iOS depending on the value type the return value would be one of: - /// - For primitive JavaScript types: the value string formatted (e.g JavaScript 100 returns '100'). - /// - For JavaScript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). + /// - For primitive Javascript types: the value string formatted (e.g Javascript 100 returns '100'). + /// - For Javascript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). /// - Other non-primitive types are not supported on iOS and will return as null. /// - /// The Future completes with an error if a JavaScript error occurred. + /// The Future completes with an error if a Javascript error occurred. /// /// When evaluating Javascript in a [WebView], it is best practice to wait for /// the [WebView.onPageFinished] callback. This guarantees all the Javascript /// embedded in the main frame HTML has been loaded. - Future runJavaScriptForResult(String javaScriptString) { + Future runJavascriptReturningResult(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { return Future.error(FlutterError( - 'JavaScript mode must be enabled/unrestricted when calling runJavaScriptForResult.')); + 'Javascript mode must be enabled/unrestricted when calling runJavascriptReturningResult.')); } - return _webViewPlatformController.runJavaScriptForResult(javaScriptString); + return _webViewPlatformController + .runJavascriptReturningResult(javaScriptString); } /// Returns the title of the currently loaded page. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index b81cf2ccf2d0..0880b416ade4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -103,11 +103,11 @@ void main() { await pageLoads.stream.firstWhere((String url) => url == currentUrl); final String content = await controller - .runJavaScriptForResult('document.documentElement.innerText'); + .runJavascriptReturningResult('document.documentElement.innerText'); expect(content.contains('flutter_test_header'), isTrue); }); - testWidgets('JavaScriptChannel', (WidgetTester tester) async { + testWidgets('JavascriptChannel', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); final Completer pageStarted = Completer(); @@ -151,7 +151,8 @@ void main() { // See: https://github.com/flutter/flutter/issues/66318#issuecomment-701105380 // TODO(cyanglaz): remove the workaround "1" in the end when the below issue is fixed. // https://github.com/flutter/flutter/issues/66318 - await controller.runJavaScriptForResult('Echo.postMessage("hello");1;'); + await controller + .runJavascriptReturningResult('Echo.postMessage("hello");1;'); expect(messagesReceived, equals(['hello'])); }); @@ -397,7 +398,8 @@ void main() { WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -426,7 +428,7 @@ void main() { controller = await controllerCompleter.future; await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -457,7 +459,8 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageLoaded = Completer(); @@ -485,7 +488,7 @@ void main() { await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); @@ -535,7 +538,7 @@ void main() { await videoPlaying.future; String fullScreen = - await controller.runJavaScriptForResult('isFullScreen();'); + await controller.runJavascriptReturningResult('isFullScreen();'); expect(fullScreen, _webviewBool(false)); }); @@ -586,7 +589,7 @@ void main() { await videoPlaying.future; String fullScreen = - await controller.runJavaScriptForResult('isFullScreen();'); + await controller.runJavascriptReturningResult('isFullScreen();'); expect(fullScreen, _webviewBool(true)); }); }); @@ -652,7 +655,8 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); controllerCompleter = Completer(); @@ -686,7 +690,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(true)); }); @@ -722,7 +726,8 @@ void main() { await pageStarted.future; await pageLoaded.future; - String isPaused = await controller.runJavaScriptForResult('isPaused();'); + String isPaused = + await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); pageStarted = Completer(); @@ -755,7 +760,7 @@ void main() { await pageStarted.future; await pageLoaded.future; - isPaused = await controller.runJavaScriptForResult('isPaused();'); + isPaused = await controller.runJavascriptReturningResult('isPaused();'); expect(isPaused, _webviewBool(false)); }); }); @@ -913,7 +918,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('location.href = "https://www.example.com/"'); + .runJavascript('location.href = "https://www.example.com/"'); await pageLoads.stream.first; // Wait for the next page load. final String? currentUrl = await controller.currentUrl(); @@ -1044,7 +1049,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('location.href = "https://www.youtube.com/"'); + .runJavascript('location.href = "https://www.youtube.com/"'); // There should never be any second page load, since our new URL is // blocked. Still wait for a potential page change for some time in order @@ -1085,7 +1090,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('location.href = "https://www.example.com"'); + .runJavascript('location.href = "https://www.example.com"'); await pageLoads.stream.first; // Wait for second page to load. final String? currentUrl = await controller.currentUrl(); @@ -1141,7 +1146,7 @@ void main() { ); final WebViewController controller = await controllerCompleter.future; await controller - .runJavaScript('window.open("https://flutter.dev/", "_blank")'); + .runJavascript('window.open("https://flutter.dev/", "_blank")'); await pageLoaded.future; final String? currentUrl = await controller.currentUrl(); expect(currentUrl, 'https://flutter.dev/'); @@ -1175,7 +1180,7 @@ void main() { await pageLoaded.future; pageLoaded = Completer(); - await controller.runJavaScript('window.open("https://www.example.com/")'); + await controller.runJavascript('window.open("https://www.example.com/")'); await pageLoaded.future; pageLoaded = Completer(); expect(controller.currentUrl(), completion('https://www.example.com/')); @@ -1189,7 +1194,7 @@ void main() { ); } -// JavaScript booleans evaluate to different string values on Android and iOS. +// Javascript booleans evaluate to different string values on Android and iOS. // This utility method returns the string boolean value of the current platform. String _webviewBool(bool value) { if (defaultTargetPlatform == TargetPlatform.iOS) { @@ -1200,13 +1205,13 @@ String _webviewBool(bool value) { /// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests. Future _getUserAgent(WebViewController controller) async { - return _runJavaScriptForResult(controller, 'navigator.userAgent;'); + return _runJavascriptReturningResult(controller, 'navigator.userAgent;'); } -Future _runJavaScriptForResult( +Future _runJavascriptReturningResult( WebViewController controller, String js) async { if (defaultTargetPlatform == TargetPlatform.iOS) { - return await controller.runJavaScriptForResult(js); + return await controller.runJavascriptReturningResult(js); } - return jsonDecode(await controller.runJavaScriptForResult(js)); + return jsonDecode(await controller.runJavascriptReturningResult(js)); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 62428d041adf..338b3e228980 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -277,13 +277,16 @@ ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 68BDCAE823C3F7CB00D9C032 = { + DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; + DevelopmentTeam = 7624MWN53C; }; F7151F73266057800028CB91 = { CreatedOnToolsVersion = 12.5; + DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; TestTargetID = 97C146ED1CF9000F007C117D; }; @@ -477,6 +480,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -491,6 +495,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -611,6 +616,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -634,6 +640,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -655,6 +662,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; @@ -668,6 +676,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m index 5d3d9e71e747..444e0f01260d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m @@ -88,7 +88,7 @@ - (void)testContentInsetsSumAlwaysZeroAfterSetFrame { } } -- (void)testRunJavaScriptFailsForNullString { +- (void)testRunJavascriptFailsForNullString { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -99,7 +99,7 @@ - (void)testRunJavaScriptFailsForNullString { [self expectationWithDescription:@"Should return error result over the method channel."]; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" arguments:nil] result:^(id _Nullable result) { XCTAssertTrue([result class] == [FlutterError class]); @@ -110,7 +110,7 @@ - (void)testRunJavaScriptFailsForNullString { [self waitForExpectationsWithTimeout:30.0 handler:nil]; } -- (void)testRunJavaScriptRunsStringWithSuccessResult { +- (void)testRunJavascriptRunsStringWithSuccessResult { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -130,8 +130,8 @@ - (void)testRunJavaScriptRunsStringWithSuccessResult { controller.webView = mockView; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" - arguments:@"Test JavaScript String"] + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" + arguments:@"Test Javascript String"] result:^(id _Nullable result) { XCTAssertNil(result); [resultExpectation fulfill]; @@ -141,7 +141,7 @@ - (void)testRunJavaScriptRunsStringWithSuccessResult { [self waitForExpectationsWithTimeout:30.0 handler:nil]; } -- (void)testRunJavaScriptReturnsErrorResultForWKError { +- (void)testRunJavascriptReturnsErrorResultForWKError { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -152,7 +152,7 @@ - (void)testRunJavaScriptReturnsErrorResultForWKError { [self expectationWithDescription:@"Should return error result over the method channel."]; NSError *testError = [NSError errorWithDomain:@"" - // Any error code but WKErrorJavaScriptResultTypeIsUnsupported + // Any error code but WKErrorJavascriptResultTypeIsUnsupported code:WKErrorJavaScriptResultTypeIsUnsupported + 1 userInfo:@{NSLocalizedDescriptionKey : @"Test Error"}]; FLTWKWebView *mockView = OCMClassMock(FLTWKWebView.class); @@ -166,8 +166,8 @@ - (void)testRunJavaScriptReturnsErrorResultForWKError { controller.webView = mockView; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" - arguments:@"Test JavaScript String"] + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" + arguments:@"Test Javascript String"] result:^(id _Nullable result) { XCTAssertTrue([result class] == [FlutterError class]); [resultExpectation fulfill]; @@ -177,7 +177,7 @@ - (void)testRunJavaScriptReturnsErrorResultForWKError { [self waitForExpectationsWithTimeout:30.0 handler:nil]; } -- (void)testRunJavaScriptReturnsSuccessForWKErrorJavaScriptResultTypeIsUnsupported { +- (void)testRunJavascriptReturnsSuccessForWKErrorJavascriptResultTypeIsUnsupported { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -200,8 +200,8 @@ - (void)testRunJavaScriptReturnsSuccessForWKErrorJavaScriptResultTypeIsUnsupport controller.webView = mockView; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScript" - arguments:@"Test JavaScript String"] + [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" + arguments:@"Test Javascript String"] result:^(id _Nullable result) { XCTAssertNil(result); [resultExpectation fulfill]; @@ -211,7 +211,7 @@ - (void)testRunJavaScriptReturnsSuccessForWKErrorJavaScriptResultTypeIsUnsupport [self waitForExpectationsWithTimeout:30.0 handler:nil]; } -- (void)testRunJavaScriptForResultFailsForNullString { +- (void)testRunJavascriptReturningResultFailsForNullString { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -222,18 +222,19 @@ - (void)testRunJavaScriptForResultFailsForNullString { [self expectationWithDescription:@"Should return error result over the method channel."]; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" - arguments:nil] - result:^(id _Nullable result) { - XCTAssertTrue([result class] == [FlutterError class]); - [resultExpectation fulfill]; - }]; + [controller + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult" + arguments:nil] + result:^(id _Nullable result) { + XCTAssertTrue([result class] == [FlutterError class]); + [resultExpectation fulfill]; + }]; // Verify [self waitForExpectationsWithTimeout:30.0 handler:nil]; } -- (void)testRunJavaScriptForResultRunsStringWithSuccessResult { +- (void)testRunJavascriptReturningResultRunsStringWithSuccessResult { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -253,18 +254,19 @@ - (void)testRunJavaScriptForResultRunsStringWithSuccessResult { controller.webView = mockView; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" - arguments:@"Test JavaScript String"] - result:^(id _Nullable result) { - XCTAssertTrue([@"RESULT" isEqualToString:result]); - [resultExpectation fulfill]; - }]; + [controller + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult" + arguments:@"Test Javascript String"] + result:^(id _Nullable result) { + XCTAssertTrue([@"RESULT" isEqualToString:result]); + [resultExpectation fulfill]; + }]; // Verify [self waitForExpectationsWithTimeout:30.0 handler:nil]; } -- (void)testRunJavaScriptForResultReturnsErrorResultForWKError { +- (void)testRunJavascriptReturningResultReturnsErrorResultForWKError { // Setup FLTWebViewController *controller = [[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400) @@ -287,12 +289,13 @@ - (void)testRunJavaScriptForResultReturnsErrorResultForWKError { controller.webView = mockView; // Run - [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavaScriptForResult" - arguments:@"Test JavaScript String"] - result:^(id _Nullable result) { - XCTAssertTrue([result class] == [FlutterError class]); - [resultExpectation fulfill]; - }]; + [controller + onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult" + arguments:@"Test Javascript String"] + result:^(id _Nullable result) { + XCTAssertTrue([result class] == [FlutterError class]); + [resultExpectation fulfill]; + }]; // Verify [self waitForExpectationsWithTimeout:30.0 handler:nil]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart index b9aae2ae0d08..d8e0fa03f9a6 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart @@ -197,16 +197,16 @@ class _SampleMenu extends StatelessWidget { void _onShowUserAgent( WebViewController controller, BuildContext context) async { - // Send a message with the user agent string to the Snackbar JavaScript channel we registered + // Send a message with the user agent string to the Snackbar Javascript channel we registered // with the WebView. - await controller.runJavaScript( + await controller.runJavascript( 'Snackbar.postMessage("User Agent: " + navigator.userAgent);'); } void _onListCookies( WebViewController controller, BuildContext context) async { final String cookies = - await controller.runJavaScriptForResult('document.cookie'); + await controller.runJavascriptReturningResult('document.cookie'); ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Column( mainAxisAlignment: MainAxisAlignment.end, @@ -220,7 +220,7 @@ class _SampleMenu extends StatelessWidget { } void _onAddToCache(WebViewController controller, BuildContext context) async { - await controller.runJavaScript( + await controller.runJavascript( 'caches.open("test_caches_entry"); localStorage["test_localStorage"] = "dummy_entry";'); ScaffoldMessenger.of(context).showSnackBar(const SnackBar( content: Text('Added a test entry to cache.'), @@ -228,7 +228,7 @@ class _SampleMenu extends StatelessWidget { } void _onListCache(WebViewController controller, BuildContext context) async { - await controller.runJavaScript('caches.keys()' + await controller.runJavascript('caches.keys()' '.then((cacheKeys) => JSON.stringify({"cacheKeys" : cacheKeys, "localStorage" : localStorage}))' '.then((caches) => Snackbar.postMessage(caches))'); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart index bfaeac0d25cd..6f68dc08ef9c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart @@ -96,11 +96,11 @@ class WebView extends StatefulWidget { /// Whether Javascript execution is enabled. final JavascriptMode javascriptMode; - /// The set of [JavascriptChannel]s available to JavaScript code running in the web view. + /// The set of [JavascriptChannel]s available to Javascript code running in the web view. /// /// For each [JavascriptChannel] in the set, a channel object is made available for the - /// JavaScript code in a window property named [JavascriptChannel.name]. - /// The JavaScript code can then call `postMessage` on that object to send a message that will be + /// Javascript code in a window property named [JavascriptChannel.name]. + /// The Javascript code can then call `postMessage` on that object to send a message that will be /// passed to [JavascriptChannel.onMessageReceived]. /// /// For example for the following JavascriptChannel: @@ -109,7 +109,7 @@ class WebView extends StatefulWidget { /// JavascriptChannel(name: 'Print', onMessageReceived: (JavascriptMessage message) { print(message.message); }); /// ``` /// - /// JavaScript code can call: + /// Javascript code can call: /// /// ```javascript /// Print.postMessage('Hello'); @@ -117,7 +117,7 @@ class WebView extends StatefulWidget { /// /// To asynchronously invoke the message handler which will print the message to standard output. /// - /// Adding a new JavaScript channel only takes affect after the next page is loaded. + /// Adding a new Javascript channel only takes affect after the next page is loaded. /// /// Set values must not be null. A [JavascriptChannel.name] cannot be the same for multiple /// channels in the list. @@ -410,41 +410,42 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } - /// Runs the given JavaScript in the context of the current page. - /// If you are looking for the result, use [runJavascriptForResult] instead. - /// The Future completes with an error if a JavaScript error occurred. + /// Runs the given Javascript in the context of the current page. + /// If you are looking for the result, use [runJavascriptReturningResult] instead. + /// The Future completes with an error if a Javascript error occurred. /// /// When running Javascript in a [WebView], it is best practice to wait for - // the [WebView.onPageFinished] callback. This guarantees all the Javascript - // embedded in the main frame HTML has been loaded. - Future runJavaScript(String javaScriptString) { + /// the [WebView.onPageFinished] callback. This guarantees all the Javascript + /// embedded in the main frame HTML has been loaded. + Future runJavascript(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { return Future.error(FlutterError( - 'JavaScript mode must be enabled/unrestricted when calling runJavaScript.')); + 'Javascript mode must be enabled/unrestricted when calling runJavascript.')); } - return _webViewPlatformController.runJavaScript(javaScriptString); + return _webViewPlatformController.runJavascript(javaScriptString); } - /// Runs the given JavaScript in the context of the current page, and returns the result. + /// Runs the given Javascript in the context of the current page, and returns the result. /// /// On Android returns the evaluation result as a JSON formatted string. /// /// On iOS depending on the value type the return value would be one of: - /// - For primitive JavaScript types: the value string formatted (e.g JavaScript 100 returns '100'). - /// - For JavaScript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). + /// - For primitive Javascript types: the value string formatted (e.g Javascript 100 returns '100'). + /// - For Javascript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). /// - Other non-primitive types are not supported on iOS and will return as null. /// - /// The Future completes with an error if a JavaScript error occurred. + /// The Future completes with an error if a Javascript error occurred. /// /// When evaluating Javascript in a [WebView], it is best practice to wait for /// the [WebView.onPageFinished] callback. This guarantees all the Javascript /// embedded in the main frame HTML has been loaded. - Future runJavaScriptForResult(String javaScriptString) { + Future runJavascriptReturningResult(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { return Future.error(FlutterError( - 'JavaScript mode must be enabled/unrestricted when calling runJavaScriptForResult.')); + 'Javascript mode must be enabled/unrestricted when calling runJavascriptReturningResult.')); } - return _webViewPlatformController.runJavaScriptForResult(javaScriptString); + return _webViewPlatformController + .runJavascriptReturningResult(javaScriptString); } /// Returns the title of the currently loaded page. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 7e28cd9c0b70..370657935e21 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -5,7 +5,7 @@ #import "FlutterWebView.h" #import "FLTWKNavigationDelegate.h" #import "FLTWKProgressionDelegate.h" -#import "JavaScriptChannelHandler.h" +#import "JavascriptChannelHandler.h" @implementation FLTWebViewFactory { NSObject* _messenger; @@ -62,8 +62,8 @@ @implementation FLTWebViewController { int64_t _viewId; FlutterMethodChannel* _channel; NSString* _currentUrl; - // The set of registered JavaScript channel names. - NSMutableSet* _javaScriptChannelNames; + // The set of registered Javascript channel names. + NSMutableSet* _javascriptChannelNames; FLTWKNavigationDelegate* _navigationDelegate; FLTWKProgressionDelegate* _progressionDelegate; } @@ -77,13 +77,13 @@ - (instancetype)initWithFrame:(CGRect)frame NSString* channelName = [NSString stringWithFormat:@"plugins.flutter.io/webview_%lld", viewId]; _channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger]; - _javaScriptChannelNames = [[NSMutableSet alloc] init]; + _javascriptChannelNames = [[NSMutableSet alloc] init]; WKUserContentController* userContentController = [[WKUserContentController alloc] init]; if ([args[@"javascriptChannelNames"] isKindOfClass:[NSArray class]]) { NSArray* javaScriptChannelNames = args[@"javascriptChannelNames"]; - [_javaScriptChannelNames addObjectsFromArray:javaScriptChannelNames]; - [self registerJavaScriptChannels:_javaScriptChannelNames controller:userContentController]; + [_javascriptChannelNames addObjectsFromArray:javaScriptChannelNames]; + [self registerJavascriptChannels:_javascriptChannelNames controller:userContentController]; } NSDictionary* settings = args[@"settings"]; @@ -150,15 +150,15 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if ([[call method] isEqualToString:@"currentUrl"]) { [self onCurrentUrl:call result:result]; } else if ([[call method] isEqualToString:@"evaluateJavascript"]) { - [self onEvaluateJavaScript:call result:result]; - } else if ([[call method] isEqualToString:@"runJavaScript"]) { - [self onRunJavaScript:call result:result]; - } else if ([[call method] isEqualToString:@"runJavaScriptForResult"]) { - [self onRunJavaScriptForResult:call result:result]; + [self onEvaluateJavascript:call result:result]; + } else if ([[call method] isEqualToString:@"runJavascript"]) { + [self onRunJavascript:call result:result]; + } else if ([[call method] isEqualToString:@"runJavascriptReturningResult"]) { + [self onRunJavascriptReturningResult:call result:result]; } else if ([[call method] isEqualToString:@"addJavascriptChannels"]) { - [self onAddJavaScriptChannels:call result:result]; + [self onAddJavascriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"removeJavascriptChannels"]) { - [self onRemoveJavaScriptChannels:call result:result]; + [self onRemoveJavascriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"clearCache"]) { [self clearCache:result]; } else if ([[call method] isEqualToString:@"getTitle"]) { @@ -226,11 +226,11 @@ - (void)onCurrentUrl:(FlutterMethodCall*)call result:(FlutterResult)result { result(_currentUrl); } -- (void)onEvaluateJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* jsString = [call arguments]; if (!jsString) { - result([FlutterError errorWithCode:@"evaluateJavaScript_failed" - message:@"JavaScript String cannot be null" + result([FlutterError errorWithCode:@"evaluateJavascript_failed" + message:@"Javascript String cannot be null" details:nil]); return; } @@ -239,8 +239,8 @@ - (void)onEvaluateJavaScript:(FlutterMethodCall*)call result:(FlutterResult)resu if (error) { result([FlutterError errorWithCode:@"evaluateJavascript_failed" - message:@"Failed evaluating JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + message:@"Failed evaluating Javascript" + details:[NSString stringWithFormat:@"Javascript string was: '%@'\n%@", jsString, error]]); } else { result([NSString stringWithFormat:@"%@", evaluateResult]); @@ -248,11 +248,11 @@ - (void)onEvaluateJavaScript:(FlutterMethodCall*)call result:(FlutterResult)resu }]; } -- (void)onRunJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onRunJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* jsString = [call arguments]; if (!jsString) { - result([FlutterError errorWithCode:@"runJavaScript_failed" - message:@"JavaScript String cannot be null" + result([FlutterError errorWithCode:@"runJavascript_failed" + message:@"Javascript String cannot be null" details:nil]); return; } @@ -260,9 +260,9 @@ - (void)onRunJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result { completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error && error.code != WKErrorJavaScriptResultTypeIsUnsupported) { result([FlutterError - errorWithCode:@"runJavaScript_failed" - message:@"Failed running JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + errorWithCode:@"runJavascript_failed" + message:@"Failed running Javascript" + details:[NSString stringWithFormat:@"Javascript string was: '%@'\n%@", jsString, error]]); } else { result(nil); @@ -270,11 +270,11 @@ - (void)onRunJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result { }]; } -- (void)onRunJavaScriptForResult:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onRunJavascriptReturningResult:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* jsString = [call arguments]; if (!jsString) { - result([FlutterError errorWithCode:@"runJavaScriptForResult_failed" - message:@"JavaScript String cannot be null" + result([FlutterError errorWithCode:@"runJavascriptReturningResult_failed" + message:@"Javascript String cannot be null" details:nil]); return; } @@ -282,9 +282,9 @@ - (void)onRunJavaScriptForResult:(FlutterMethodCall*)call result:(FlutterResult) completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error) { result([FlutterError - errorWithCode:@"runJavaScriptForResult_failed" - message:@"Failed running JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + errorWithCode:@"runJavascriptReturningResult_failed" + message:@"Failed running Javascript" + details:[NSString stringWithFormat:@"Javascript string was: '%@'\n%@", jsString, error]]); } else { result([NSString stringWithFormat:@"%@", evaluateResult]); @@ -292,29 +292,29 @@ - (void)onRunJavaScriptForResult:(FlutterMethodCall*)call result:(FlutterResult) }]; } -- (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onAddJavascriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { NSArray* channelNames = [call arguments]; NSSet* channelNamesSet = [[NSSet alloc] initWithArray:channelNames]; - [_javaScriptChannelNames addObjectsFromArray:channelNames]; - [self registerJavaScriptChannels:channelNamesSet + [_javascriptChannelNames addObjectsFromArray:channelNames]; + [self registerJavascriptChannels:channelNamesSet controller:_webView.configuration.userContentController]; result(nil); } -- (void)onRemoveJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onRemoveJavascriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { // WkWebView does not support removing a single user script, so instead we remove all // user scripts, all message handlers. And re-register channels that shouldn't be removed. [_webView.configuration.userContentController removeAllUserScripts]; - for (NSString* channelName in _javaScriptChannelNames) { + for (NSString* channelName in _javascriptChannelNames) { [_webView.configuration.userContentController removeScriptMessageHandlerForName:channelName]; } NSArray* channelNamesToRemove = [call arguments]; for (NSString* channelName in channelNamesToRemove) { - [_javaScriptChannelNames removeObject:channelName]; + [_javascriptChannelNames removeObject:channelName]; } - [self registerJavaScriptChannels:_javaScriptChannelNames + [self registerJavascriptChannels:_javascriptChannelNames controller:_webView.configuration.userContentController]; result(nil); } @@ -429,7 +429,7 @@ - (void)updateJsMode:(NSNumber*)mode { [preferences setJavaScriptEnabled:YES]; break; default: - NSLog(@"webview_flutter: unknown JavaScript mode: %@", mode); + NSLog(@"webview_flutter: unknown Javascript mode: %@", mode); } } @@ -498,12 +498,12 @@ - (bool)loadUrl:(NSString*)url withHeaders:(NSDictionary*) return true; } -- (void)registerJavaScriptChannels:(NSSet*)channelNames +- (void)registerJavascriptChannels:(NSSet*)channelNames controller:(WKUserContentController*)userContentController { for (NSString* channelName in channelNames) { - FLTJavaScriptChannel* channel = - [[FLTJavaScriptChannel alloc] initWithMethodChannel:_channel - javaScriptChannelName:channelName]; + FLTJavascriptChannel* channel = + [[FLTJavascriptChannel alloc] initWithMethodChannel:_channel + javascriptChannelName:channelName]; [userContentController addScriptMessageHandler:channel name:channelName]; NSString* wrapperSource = [NSString stringWithFormat:@"window.%@ = webkit.messageHandlers.%@;", channelName, channelName]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.h similarity index 73% rename from packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h rename to packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.h index a0a5ec657295..dedadb4c8fb1 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.h @@ -7,10 +7,10 @@ NS_ASSUME_NONNULL_BEGIN -@interface FLTJavaScriptChannel : NSObject +@interface FLTJavascriptChannel : NSObject - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - javaScriptChannelName:(NSString*)javaScriptChannelName; + javascriptChannelName:(NSString*)javascriptChannelName; @end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m similarity index 65% rename from packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m rename to packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m index ec9a363a4b2e..8a9d236b8767 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m @@ -2,32 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "JavaScriptChannelHandler.h" +#import "JavascriptChannelHandler.h" -@implementation FLTJavaScriptChannel { +@implementation FLTJavascriptChannel { FlutterMethodChannel* _methodChannel; - NSString* _javaScriptChannelName; + NSString* _javascriptChannelName; } - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - javaScriptChannelName:(NSString*)javaScriptChannelName { + javascriptChannelName:(NSString*)javascriptChannelName { self = [super init]; NSAssert(methodChannel != nil, @"methodChannel must not be null."); - NSAssert(javaScriptChannelName != nil, @"javaScriptChannelName must not be null."); + NSAssert(javascriptChannelName != nil, @"javascriptChannelName must not be null."); if (self) { _methodChannel = methodChannel; - _javaScriptChannelName = javaScriptChannelName; + _javascriptChannelName = javascriptChannelName; } return self; } - (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message { - NSAssert(_methodChannel != nil, @"Can't send a message to an unitialized JavaScript channel."); - NSAssert(_javaScriptChannelName != nil, - @"Can't send a message to an unitialized JavaScript channel."); + NSAssert(_methodChannel != nil, @"Can't send a message to an unitialized Javascript channel."); + NSAssert(_javascriptChannelName != nil, + @"Can't send a message to an unitialized Javascript channel."); NSDictionary* arguments = @{ - @"channel" : _javaScriptChannelName, + @"channel" : _javascriptChannelName, @"message" : [NSString stringWithFormat:@"%@", message.body] }; [_methodChannel invokeMethod:@"javascriptChannelMessage" arguments:arguments]; From 3d8b9ceb0465707b4e2a1272b5bcc84ee6b4a8b8 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Mon, 4 Oct 2021 15:14:00 +0200 Subject: [PATCH 11/36] Update changelog --- packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index f8fa3b4d7ecd..245e9c9d4a3f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.1.0 -* Implemented new `runJavaScript` and `runJavaScriptForResult` methods in platform interface. +* Implemented new `runJavascript` and `runJavascriptReturningResult` methods in platform interface. ## 2.0.14 From 0ecf6410b57a60cd0835049601b2e1f3dd803702 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Mon, 4 Oct 2021 16:19:52 +0200 Subject: [PATCH 12/36] Revert inclusion of development team --- .../example/ios/Runner.xcodeproj/project.pbxproj | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 338b3e228980..62428d041adf 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -277,16 +277,13 @@ ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 68BDCAE823C3F7CB00D9C032 = { - DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; - DevelopmentTeam = 7624MWN53C; }; F7151F73266057800028CB91 = { CreatedOnToolsVersion = 12.5; - DevelopmentTeam = 7624MWN53C; ProvisioningStyle = Automatic; TestTargetID = 97C146ED1CF9000F007C117D; }; @@ -480,7 +477,6 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -495,7 +491,6 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; @@ -616,7 +611,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -640,7 +634,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = 7624MWN53C; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -662,7 +655,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; @@ -676,7 +668,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = 7624MWN53C; INFOPLIST_FILE = RunnerUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_FAST_MATH = YES; From 02e110615d6aad47950de86098a6e7181712eb86 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Tue, 5 Oct 2021 14:18:54 +0200 Subject: [PATCH 13/36] Implement PR feedback --- .../CHANGELOG.md | 2 +- .../webview_platform_controller.dart | 24 +++++++++---------- .../lib/src/types/javascript_channel.dart | 6 ++--- .../webview_method_channel_test.dart | 16 ++++++------- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md index d15755699a79..295554aed61a 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.1.0 -* Added `runJavascript` and `runJavascriptReturningResult` interface methods to supersede `evaluateJavaScript`. +* Added `runJavascript` and `runJavascriptReturningResult` interface methods to supersede `evaluateJavascript`. ## 1.0.0 diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart index ea0469706128..b42da4326079 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/platform_interface/webview_platform_controller.dart @@ -103,38 +103,38 @@ abstract class WebViewPlatformController { "WebView clearCache is not implemented on the current platform"); } - /// Evaluates a Javascript expression in the context of the current page. + /// Evaluates a JavaScript expression in the context of the current page. /// - /// The Future completes with an error if a Javascript error occurred, or if the type of the - /// evaluated expression is not supported (e.g on iOS not all non primitive types can be evaluated). + /// The Future completes with an error if a JavaScript error occurred, or if the type of the + /// evaluated expression is not supported (e.g on iOS not all non-primitive types can be evaluated). Future evaluateJavascript(String javascript) { throw UnimplementedError( "WebView evaluateJavascript is not implemented on the current platform"); } - /// Runs the given Javascript in the context of the current page. + /// Runs the given JavaScript in the context of the current page. /// - /// The Future completes with an error if a Javascript error occurred. + /// The Future completes with an error if a JavaScript error occurred. Future runJavascript(String javascript) { throw UnimplementedError( "WebView runJavascript is not implemented on the current platform"); } - /// Runs the given Javascript in the context of the current page, and returns the result. + /// Runs the given JavaScript in the context of the current page, and returns the result. /// - /// The Future completes with an error if a Javascript error occurred, or if the + /// The Future completes with an error if a JavaScript error occurred, or if the /// type the given expression evaluates to is unsupported. Unsupported values include - /// certain non primitive types on iOS, as well as `undefined` or `null` on iOS 14+. + /// certain non-primitive types on iOS, as well as `undefined` or `null` on iOS 14+. Future runJavascriptReturningResult(String javascript) { throw UnimplementedError( "WebView runJavascriptReturningResult is not implemented on the current platform"); } - /// Adds new Javascript channels to the set of enabled channels. + /// Adds new JavaScript channels to the set of enabled channels. /// /// For each value in this list the platform's webview should make sure that a corresponding - /// property with a postMessage method is set on `window`. For example for a Javascript channel - /// named `Foo` it should be possible for Javascript code executing in the webview to do + /// property with a postMessage method is set on `window`. For example for a JavaScript channel + /// named `Foo` it should be possible for JavaScript code executing in the webview to do /// /// ```javascript /// Foo.postMessage('hello'); @@ -146,7 +146,7 @@ abstract class WebViewPlatformController { "WebView addJavascriptChannels is not implemented on the current platform"); } - /// Removes Javascript channel names from the set of enabled channels. + /// Removes JavaScript channel names from the set of enabled channels. /// /// This disables channels that were previously enabled by [addJavascriptChannels] or through /// [CreationParams.javascriptChannelNames]. diff --git a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/javascript_channel.dart b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/javascript_channel.dart index 8b31f5b6061e..f32a41893eb5 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/javascript_channel.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/lib/src/types/javascript_channel.dart @@ -4,14 +4,14 @@ import 'javascript_message.dart'; -/// Callback type for handling messages sent from Javascript running in a web view. +/// Callback type for handling messages sent from JavaScript running in a web view. typedef void JavascriptMessageHandler(JavascriptMessage message); final RegExp _validChannelNames = RegExp('^[a-zA-Z_][a-zA-Z0-9_]*\$'); /// A named channel for receiving messaged from JavaScript code running inside a web view. class JavascriptChannel { - /// Constructs a Javascript channel. + /// Constructs a JavaScript channel. /// /// The parameters `name` and `onMessageReceived` must not be null. JavascriptChannel({ @@ -24,7 +24,7 @@ class JavascriptChannel { /// The channel's name. /// /// Passing this channel object as part of a [WebView.javascriptChannels] adds a channel object to - /// the Javascript window object's property named `name`. + /// the JavaScript window object's property named `name`. /// /// The name must start with a letter or underscore(_), followed by any combination of those /// characters plus digits. diff --git a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart index 1eee15547908..bf4fb1d1ad58 100644 --- a/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart +++ b/packages/webview_flutter/webview_flutter_platform_interface/test/src/method_channel/webview_method_channel_test.dart @@ -266,16 +266,16 @@ void main() { test('evaluateJavascript', () async { final String evaluateJavascript = await webViewPlatform.evaluateJavascript( - 'This simulates some Javascript code.', + 'This simulates some JavaScript code.', ); - expect('This simulates some Javascript code.', evaluateJavascript); + expect('This simulates some JavaScript code.', evaluateJavascript); expect( log, [ isMethodCall( 'evaluateJavascript', - arguments: 'This simulates some Javascript code.', + arguments: 'This simulates some JavaScript code.', ), ], ); @@ -283,7 +283,7 @@ void main() { test('runJavascript', () async { await webViewPlatform.runJavascript( - 'This simulates some Javascript code.', + 'This simulates some JavaScript code.', ); expect( @@ -291,7 +291,7 @@ void main() { [ isMethodCall( 'runJavascript', - arguments: 'This simulates some Javascript code.', + arguments: 'This simulates some JavaScript code.', ), ], ); @@ -300,16 +300,16 @@ void main() { test('runJavascriptReturningResult', () async { final String evaluateJavascript = await webViewPlatform.runJavascriptReturningResult( - 'This simulates some Javascript code.', + 'This simulates some JavaScript code.', ); - expect('This simulates some Javascript code.', evaluateJavascript); + expect('This simulates some JavaScript code.', evaluateJavascript); expect( log, [ isMethodCall( 'runJavascriptReturningResult', - arguments: 'This simulates some Javascript code.', + arguments: 'This simulates some JavaScript code.', ), ], ); From d8f51edcf1f03378dfc34b82dce25cd40f6b6e52 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Tue, 5 Oct 2021 15:01:48 +0200 Subject: [PATCH 14/36] Implemented platform interface PR feedback --- .../webviewflutter/FlutterWebView.java | 2 +- .../webviewflutter/FlutterWebViewTest.java | 14 +++---- .../webview_flutter_test.dart | 4 +- .../example/lib/main.dart | 4 +- .../example/lib/web_view.dart | 38 ++++++++--------- .../webview_flutter_test.dart | 2 +- .../example/ios/RunnerTests/FLTWebViewTests.m | 10 ++--- .../example/lib/main.dart | 4 +- .../example/lib/web_view.dart | 41 +++++++++---------- .../ios/Classes/FlutterWebView.m | 22 +++++----- .../ios/Classes/JavascriptChannelHandler.m | 4 +- 11 files changed, 69 insertions(+), 76 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index 1b79012148ee..7033c23c03ec 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -149,7 +149,7 @@ public void onProgressChanged(WebView view, int progress) { * *

    *
  • always enable the DOM storage API; - *
  • always allow Javascript to automatically open windows; + *
  • always allow JavaScript to automatically open windows; *
  • always allow support for multiple windows; *
  • always use the {@link FlutterWebChromeClient} as web Chrome client. *
diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java index 705c46ea5130..0354ad66d7e3 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java @@ -112,20 +112,20 @@ public void evaluateJavascript_shouldReturnValueOnSuccessForReturnValue() { doAnswer( invocation -> { android.webkit.ValueCallback callback = invocation.getArgument(1); - callback.onReceiveValue("Test Javascript Result"); + callback.onReceiveValue("Test JavaScript Result"); return null; }) .when(mockWebView) - .evaluateJavascript(eq("Test Javascript String"), any()); + .evaluateJavascript(eq("Test JavaScript String"), any()); FlutterWebView flutterWebView = new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); // Run flutterWebView.onMethodCall( - new MethodCall("runJavascriptReturningResult", "Test Javascript String"), mockResult); + new MethodCall("runJavascriptReturningResult", "Test JavaScript String"), mockResult); // Verify - verify(mockResult, times(1)).success("Test Javascript Result"); + verify(mockResult, times(1)).success("Test JavaScript Result"); } } @@ -145,17 +145,17 @@ public void evaluateJavascript_shouldReturnNilOnSuccessForNoReturnValue() { doAnswer( invocation -> { android.webkit.ValueCallback callback = invocation.getArgument(1); - callback.onReceiveValue("Test Javascript Result"); + callback.onReceiveValue("Test JavaScript Result"); return null; }) .when(mockWebView) - .evaluateJavascript(eq("Test Javascript String"), any()); + .evaluateJavascript(eq("Test JavaScript String"), any()); FlutterWebView flutterWebView = new FlutterWebView(mockContext, mockMethodChannel, new HashMap(), null); // Run flutterWebView.onMethodCall( - new MethodCall("runJavascript", "Test Javascript String"), mockResult); + new MethodCall("runJavascript", "Test JavaScript String"), mockResult); // Verify verify(mockResult, times(1)).success(isNull()); diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index d90df56fa875..74da9ea413d6 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -1329,7 +1329,7 @@ void main() { ); testWidgets( - 'javascript does not run in parent window', + 'JavaScript does not run in parent window', (WidgetTester tester) async { final String iframe = ''' @@ -1397,7 +1397,7 @@ void main() { ); } -// Javascript booleans evaluate to different string values on Android and iOS. +// JavaScript booleans evaluate to different string values on Android and iOS. // This utility method returns the string boolean value of the current platform. String _webviewBool(bool value) { if (defaultTargetPlatform == TargetPlatform.iOS) { diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart index 091ee94b2771..a22d165a6ff3 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/main.dart @@ -193,7 +193,7 @@ class _SampleMenu extends StatelessWidget { void _onShowUserAgent( WebViewController controller, BuildContext context) async { - // Send a message with the user agent string to the Snackbar Javascript channel we registered + // Send a message with the user agent string to the Snackbar JavaScript channel we registered // with the WebView. await controller.runJavascript( 'Snackbar.postMessage("User Agent: " + navigator.userAgent);'); @@ -340,5 +340,5 @@ class _NavigationControls extends StatelessWidget { } } -/// Callback type for handling messages sent from Javascript running in a web view. +/// Callback type for handling messages sent from JavaScript running in a web view. typedef void JavascriptMessageHandler(JavascriptMessage message); diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart index 63d69483fb03..8ed2198ea4ee 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart @@ -115,23 +115,23 @@ class WebView extends StatefulWidget { /// The initial URL to load. final String? initialUrl; - /// Whether Javascript execution is enabled. + /// Whether JavaScript execution is enabled. final JavascriptMode javascriptMode; /// The set of [JavascriptChannel]s available to Javascript code running in the web view. /// /// For each [JavascriptChannel] in the set, a channel object is made available for the - /// Javascript code in a window property named [JavascriptChannel.name]. - /// The Javascript code can then call `postMessage` on that object to send a message that will be + /// JavaScript code in a window property named [JavascriptChannel.name]. + /// The JavaScript code can then call `postMessage` on that object to send a message that will be /// passed to [JavascriptChannel.onMessageReceived]. /// - /// For example for the following JavascriptChannel: + /// For example for the following [JavascriptChannel]: /// /// ```dart /// JavascriptChannel(name: 'Print', onMessageReceived: (JavascriptMessage message) { print(message.message); }); /// ``` /// - /// Javascript code can call: + /// JavaScript code can call: /// /// ```javascript /// Print.postMessage('Hello'); @@ -139,7 +139,7 @@ class WebView extends StatefulWidget { /// /// To asynchronously invoke the message handler which will print the message to standard output. /// - /// Adding a new Javascript channel only takes affect after the next page is loaded. + /// Adding a new JavaScript channel only takes affect after the next page is loaded. /// /// Set values must not be null. A [JavascriptChannel.name] cannot be the same for multiple /// channels in the list. @@ -188,7 +188,7 @@ class WebView extends StatefulWidget { /// When [onPageFinished] is invoked on Android, the page being rendered may /// not be updated yet. /// - /// When invoked on iOS or Android, any Javascript code that is embedded + /// When invoked on iOS or Android, any JavaScript code that is embedded /// directly in the HTML has been loaded and code injected with /// [WebViewController.evaluateJavascript] can assume this. final PageFinishedCallback? onPageFinished; @@ -481,12 +481,12 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } - /// Runs the given Javascript in the context of the current page. + /// Runs the given JavaScript in the context of the current page. /// If you are looking for the result, use [runJavascriptReturningResult] instead. - /// The Future completes with an error if a Javascript error occurred. + /// The Future completes with an error if a JavaScript error occurred. /// - /// When running Javascript in a [WebView], it is best practice to wait for - // the [WebView.onPageFinished] callback. This guarantees all the Javascript + /// When running JavaScript in a [WebView], it is best practice to wait for + // the [WebView.onPageFinished] callback. This guarantees all the JavaScript // embedded in the main frame HTML has been loaded. Future runJavascript(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { @@ -496,19 +496,13 @@ class WebViewController { return _webViewPlatformController.runJavascript(javaScriptString); } - /// Runs the given Javascript in the context of the current page, and returns the result. + /// Runs the given JavaScript in the context of the current page, and returns the result. /// - /// On Android returns the evaluation result as a JSON formatted string. + /// Returns the evaluation result as a JSON formatted string. + /// The Future completes with an error if a JavaScript error occurred. /// - /// On iOS depending on the value type the return value would be one of: - /// - For primitive Javascript types: the value string formatted (e.g Javascript 100 returns '100'). - /// - For Javascript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). - /// - Other non-primitive types are not supported on iOS and will return as null. - /// - /// The Future completes with an error if a Javascript error occurred. - /// - /// When evaluating Javascript in a [WebView], it is best practice to wait for - /// the [WebView.onPageFinished] callback. This guarantees all the Javascript + /// When evaluating JavaScript in a [WebView], it is best practice to wait for + /// the [WebView.onPageFinished] callback. This guarantees all the JavaScript /// embedded in the main frame HTML has been loaded. Future runJavascriptReturningResult(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 0880b416ade4..9c666c399075 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -1194,7 +1194,7 @@ void main() { ); } -// Javascript booleans evaluate to different string values on Android and iOS. +// JavaScript booleans evaluate to different string values on Android and iOS. // This utility method returns the string boolean value of the current platform. String _webviewBool(bool value) { if (defaultTargetPlatform == TargetPlatform.iOS) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m index 444e0f01260d..9d127c2c4aaa 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/FLTWebViewTests.m @@ -131,7 +131,7 @@ - (void)testRunJavascriptRunsStringWithSuccessResult { // Run [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" - arguments:@"Test Javascript String"] + arguments:@"Test JavaScript String"] result:^(id _Nullable result) { XCTAssertNil(result); [resultExpectation fulfill]; @@ -167,7 +167,7 @@ - (void)testRunJavascriptReturnsErrorResultForWKError { // Run [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" - arguments:@"Test Javascript String"] + arguments:@"Test JavaScript String"] result:^(id _Nullable result) { XCTAssertTrue([result class] == [FlutterError class]); [resultExpectation fulfill]; @@ -201,7 +201,7 @@ - (void)testRunJavascriptReturnsSuccessForWKErrorJavascriptResultTypeIsUnsupport // Run [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascript" - arguments:@"Test Javascript String"] + arguments:@"Test JavaScript String"] result:^(id _Nullable result) { XCTAssertNil(result); [resultExpectation fulfill]; @@ -256,7 +256,7 @@ - (void)testRunJavascriptReturningResultRunsStringWithSuccessResult { // Run [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult" - arguments:@"Test Javascript String"] + arguments:@"Test JavaScript String"] result:^(id _Nullable result) { XCTAssertTrue([@"RESULT" isEqualToString:result]); [resultExpectation fulfill]; @@ -291,7 +291,7 @@ - (void)testRunJavascriptReturningResultReturnsErrorResultForWKError { // Run [controller onMethodCall:[FlutterMethodCall methodCallWithMethodName:@"runJavascriptReturningResult" - arguments:@"Test Javascript String"] + arguments:@"Test JavaScript String"] result:^(id _Nullable result) { XCTAssertTrue([result class] == [FlutterError class]); [resultExpectation fulfill]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart index d8e0fa03f9a6..21240f63ec1a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart @@ -197,7 +197,7 @@ class _SampleMenu extends StatelessWidget { void _onShowUserAgent( WebViewController controller, BuildContext context) async { - // Send a message with the user agent string to the Snackbar Javascript channel we registered + // Send a message with the user agent string to the Snackbar JavaScript channel we registered // with the WebView. await controller.runJavascript( 'Snackbar.postMessage("User Agent: " + navigator.userAgent);'); @@ -340,5 +340,5 @@ class _NavigationControls extends StatelessWidget { } } -/// Callback type for handling messages sent from Javascript running in a web view. +/// Callback type for handling messages sent from JavaScript running in a web view. typedef void JavascriptMessageHandler(JavascriptMessage message); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart index 6f68dc08ef9c..2da345171237 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart @@ -93,14 +93,14 @@ class WebView extends StatefulWidget { /// The initial URL to load. final String? initialUrl; - /// Whether Javascript execution is enabled. + /// Whether JavaScript execution is enabled. final JavascriptMode javascriptMode; - /// The set of [JavascriptChannel]s available to Javascript code running in the web view. + /// The set of [JavascriptChannel]s available to JavaScript code running in the web view. /// /// For each [JavascriptChannel] in the set, a channel object is made available for the - /// Javascript code in a window property named [JavascriptChannel.name]. - /// The Javascript code can then call `postMessage` on that object to send a message that will be + /// JavaScript code in a window property named [JavascriptChannel.name]. + /// The JavaScript code can then call `postMessage` on that object to send a message that will be /// passed to [JavascriptChannel.onMessageReceived]. /// /// For example for the following JavascriptChannel: @@ -109,7 +109,7 @@ class WebView extends StatefulWidget { /// JavascriptChannel(name: 'Print', onMessageReceived: (JavascriptMessage message) { print(message.message); }); /// ``` /// - /// Javascript code can call: + /// JavaScript code can call: /// /// ```javascript /// Print.postMessage('Hello'); @@ -117,7 +117,7 @@ class WebView extends StatefulWidget { /// /// To asynchronously invoke the message handler which will print the message to standard output. /// - /// Adding a new Javascript channel only takes affect after the next page is loaded. + /// Adding a new JavaScript channel only takes affect after the next page is loaded. /// /// Set values must not be null. A [JavascriptChannel.name] cannot be the same for multiple /// channels in the list. @@ -166,7 +166,7 @@ class WebView extends StatefulWidget { /// When [onPageFinished] is invoked on Android, the page being rendered may /// not be updated yet. /// - /// When invoked on iOS or Android, any Javascript code that is embedded + /// When invoked on iOS or Android, any JavaScript code that is embedded /// directly in the HTML has been loaded and code injected with /// [WebViewController.evaluateJavascript] can assume this. final PageFinishedCallback? onPageFinished; @@ -410,12 +410,12 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } - /// Runs the given Javascript in the context of the current page. + /// Runs the given JavaScript in the context of the current page. /// If you are looking for the result, use [runJavascriptReturningResult] instead. - /// The Future completes with an error if a Javascript error occurred. + /// The Future completes with an error if a JavaScript error occurred. /// - /// When running Javascript in a [WebView], it is best practice to wait for - /// the [WebView.onPageFinished] callback. This guarantees all the Javascript + /// When running JavaScript in a [WebView], it is best practice to wait for + /// the [WebView.onPageFinished] callback. This guarantees all the JavaScript /// embedded in the main frame HTML has been loaded. Future runJavascript(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { @@ -425,19 +425,18 @@ class WebViewController { return _webViewPlatformController.runJavascript(javaScriptString); } - /// Runs the given Javascript in the context of the current page, and returns the result. + /// Runs the given JavaScript in the context of the current page, and returns the result. /// - /// On Android returns the evaluation result as a JSON formatted string. + /// Depending on the value type the return value would be one of: + /// - For primitive JavaScript types: the value string formatted (e.g JavaScript 100 returns '100'). + /// - For JavaScript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). /// - /// On iOS depending on the value type the return value would be one of: - /// - For primitive Javascript types: the value string formatted (e.g Javascript 100 returns '100'). - /// - For Javascript arrays of supported types: a string formatted NSArray(e.g '(1,2,3), note that the string for NSArray is formatted and might contain newlines and extra spaces.'). - /// - Other non-primitive types are not supported on iOS and will return as null. + /// The Future completes with an error if a JavaScript error occurred, or if the + /// type the given expression evaluates to is unsupported. Unsupported values include + /// certain non primitive types, as well as `undefined` or `null` on iOS 14+. /// - /// The Future completes with an error if a Javascript error occurred. - /// - /// When evaluating Javascript in a [WebView], it is best practice to wait for - /// the [WebView.onPageFinished] callback. This guarantees all the Javascript + /// When evaluating JavaScript in a [WebView], it is best practice to wait for + /// the [WebView.onPageFinished] callback. This guarantees all the JavaScript /// embedded in the main frame HTML has been loaded. Future runJavascriptReturningResult(String javaScriptString) { if (_settings.javascriptMode == JavascriptMode.disabled) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 370657935e21..62215bdffbab 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -62,7 +62,7 @@ @implementation FLTWebViewController { int64_t _viewId; FlutterMethodChannel* _channel; NSString* _currentUrl; - // The set of registered Javascript channel names. + // The set of registered JavaScript channel names. NSMutableSet* _javascriptChannelNames; FLTWKNavigationDelegate* _navigationDelegate; FLTWKProgressionDelegate* _progressionDelegate; @@ -230,7 +230,7 @@ - (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)resu NSString* jsString = [call arguments]; if (!jsString) { result([FlutterError errorWithCode:@"evaluateJavascript_failed" - message:@"Javascript String cannot be null" + message:@"JavaScript String cannot be null" details:nil]); return; } @@ -239,8 +239,8 @@ - (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)resu if (error) { result([FlutterError errorWithCode:@"evaluateJavascript_failed" - message:@"Failed evaluating Javascript" - details:[NSString stringWithFormat:@"Javascript string was: '%@'\n%@", + message:@"Failed evaluating JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", jsString, error]]); } else { result([NSString stringWithFormat:@"%@", evaluateResult]); @@ -252,7 +252,7 @@ - (void)onRunJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* jsString = [call arguments]; if (!jsString) { result([FlutterError errorWithCode:@"runJavascript_failed" - message:@"Javascript String cannot be null" + message:@"JavaScript String cannot be null" details:nil]); return; } @@ -261,8 +261,8 @@ - (void)onRunJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { if (error && error.code != WKErrorJavaScriptResultTypeIsUnsupported) { result([FlutterError errorWithCode:@"runJavascript_failed" - message:@"Failed running Javascript" - details:[NSString stringWithFormat:@"Javascript string was: '%@'\n%@", + message:@"Failed running JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", jsString, error]]); } else { result(nil); @@ -274,7 +274,7 @@ - (void)onRunJavascriptReturningResult:(FlutterMethodCall*)call result:(FlutterR NSString* jsString = [call arguments]; if (!jsString) { result([FlutterError errorWithCode:@"runJavascriptReturningResult_failed" - message:@"Javascript String cannot be null" + message:@"JavaScript String cannot be null" details:nil]); return; } @@ -283,8 +283,8 @@ - (void)onRunJavascriptReturningResult:(FlutterMethodCall*)call result:(FlutterR if (error) { result([FlutterError errorWithCode:@"runJavascriptReturningResult_failed" - message:@"Failed running Javascript" - details:[NSString stringWithFormat:@"Javascript string was: '%@'\n%@", + message:@"Failed running JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", jsString, error]]); } else { result([NSString stringWithFormat:@"%@", evaluateResult]); @@ -429,7 +429,7 @@ - (void)updateJsMode:(NSNumber*)mode { [preferences setJavaScriptEnabled:YES]; break; default: - NSLog(@"webview_flutter: unknown Javascript mode: %@", mode); + NSLog(@"webview_flutter: unknown JavaScript mode: %@", mode); } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m index 8a9d236b8767..8bd8cea26f0e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m @@ -23,9 +23,9 @@ - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message { - NSAssert(_methodChannel != nil, @"Can't send a message to an unitialized Javascript channel."); + NSAssert(_methodChannel != nil, @"Can't send a message to an unitialized JavaScript channel."); NSAssert(_javascriptChannelName != nil, - @"Can't send a message to an unitialized Javascript channel."); + @"Can't send a message to an unitialized JavaScript channel."); NSDictionary* arguments = @{ @"channel" : _javascriptChannelName, @"message" : [NSString stringWithFormat:@"%@", message.body] From bfcacdc3d2fe9adacc9a8ba784f0ce19ffc7696c Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Wed, 6 Oct 2021 12:58:53 +0200 Subject: [PATCH 15/36] Update pubspec dependency --- .../webview_flutter/webview_flutter_android/pubspec.yaml | 5 +---- .../webview_flutter/webview_flutter_wkwebview/pubspec.yaml | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 76605aef3262..18f498875272 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -19,10 +19,7 @@ flutter: dependencies: flutter: sdk: flutter - - # TODO (BeMacized): Change to version dependency once interface is published - webview_flutter_platform_interface: - path: ../webview_flutter_platform_interface + webview_flutter_platform_interface: ^1.2.0 dev_dependencies: flutter_driver: diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index e070845a1a0f..bfa4b8050e90 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -18,10 +18,7 @@ flutter: dependencies: flutter: sdk: flutter - - # TODO (BeMacized): Change to version dependency once interface is published - webview_flutter_platform_interface: - path: ../webview_flutter_platform_interface + webview_flutter_platform_interface: ^1.2.0 dev_dependencies: flutter_driver: From 485ead33df51973d8c016fc672b37bb8d6afd1fa Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Wed, 6 Oct 2021 13:03:04 +0200 Subject: [PATCH 16/36] Fixed capitalisation --- .../io/flutter/plugins/webviewflutter/FlutterWebView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index 7033c23c03ec..cfc6360507aa 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -333,7 +333,7 @@ private void evaluateJavascript( MethodCall methodCall, final Result result, final boolean returnValue) { String jsString = (String) methodCall.arguments; if (jsString == null) { - throw new UnsupportedOperationException("Javascript string cannot be null"); + throw new UnsupportedOperationException("JavaScript string cannot be null"); } webView.evaluateJavascript( jsString, @@ -452,7 +452,7 @@ private void updateJsMode(int mode) { webView.getSettings().setJavaScriptEnabled(true); break; default: - throw new IllegalArgumentException("Trying to set unknown Javascript mode: " + mode); + throw new IllegalArgumentException("Trying to set unknown JavaScript mode: " + mode); } } From a7d10c0e078cba7bbf9fe58b2051717c93b4cac9 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Wed, 6 Oct 2021 13:06:59 +0200 Subject: [PATCH 17/36] Fixed capitalisation --- .../webview_flutter_android/example/lib/web_view.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart index 8ed2198ea4ee..0f9eed75656d 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart @@ -118,7 +118,7 @@ class WebView extends StatefulWidget { /// Whether JavaScript execution is enabled. final JavascriptMode javascriptMode; - /// The set of [JavascriptChannel]s available to Javascript code running in the web view. + /// The set of [JavascriptChannel]s available to JavaScript code running in the web view. /// /// For each [JavascriptChannel] in the set, a channel object is made available for the /// JavaScript code in a window property named [JavascriptChannel.name]. From d98bc6a67171170ed587703b0af31e7ab9c109b2 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Thu, 7 Oct 2021 12:41:23 +0200 Subject: [PATCH 18/36] Fix warning --- .../webview_flutter_wkwebview/ios/Classes/FlutterWebView.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 62215bdffbab..4f4fdd9fb4cc 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -258,7 +258,12 @@ - (void)onRunJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { } [_webView evaluateJavaScript:jsString completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { - if (error && error.code != WKErrorJavaScriptResultTypeIsUnsupported) { + BOOL unsupportedTypeError = false; + if (@available(iOS 9, *)) { + unsupportedTypeError = + error && error.code == WKErrorJavaScriptResultTypeIsUnsupported; + } + if (error && !unsupportedTypeError) { result([FlutterError errorWithCode:@"runJavascript_failed" message:@"Failed running JavaScript" From 738a9ade3ffee077fd548eaad564dac61f513fc6 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:04:38 +0200 Subject: [PATCH 19/36] Partially implement PR feedback --- .../webviewflutter/FlutterWebView.java | 22 +++--- .../webviewflutter/JavaScriptChannel.java | 14 ++-- .../webviewflutter/FlutterWebViewTest.java | 6 +- .../webview_flutter_test.dart | 10 +-- .../ios/Classes/FlutterWebView.m | 77 +++++++++---------- ...elHandler.h => JavaScriptChannelHandler.h} | 4 +- ...elHandler.m => JavaScriptChannelHandler.m} | 16 ++-- 7 files changed, 73 insertions(+), 76 deletions(-) rename packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/{JavascriptChannelHandler.h => JavaScriptChannelHandler.h} (70%) rename packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/{JavascriptChannelHandler.m => JavaScriptChannelHandler.m} (72%) diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java index cfc6360507aa..1696e39f7e0c 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java @@ -123,7 +123,7 @@ public void onProgressChanged(WebView view, int progress) { if (params.containsKey(JS_CHANNEL_NAMES_FIELD)) { List names = (List) params.get(JS_CHANNEL_NAMES_FIELD); if (names != null) { - registerJavascriptChannelNames(names); + registerJavaScriptChannelNames(names); } } @@ -245,16 +245,16 @@ public void onMethodCall(MethodCall methodCall, Result result) { break; case "evaluateJavascript": case "runJavascriptReturningResult": - evaluateJavascript(methodCall, result, true); + evaluateJavaScript(methodCall, result, true); break; case "runJavascript": - evaluateJavascript(methodCall, result, false); + evaluateJavaScript(methodCall, result, false); break; case "addJavascriptChannels": - addJavascriptChannels(methodCall, result); + addJavaScriptChannels(methodCall, result); break; case "removeJavascriptChannels": - removeJavascriptChannels(methodCall, result); + removeJavaScriptChannels(methodCall, result); break; case "clearCache": clearCache(result); @@ -329,7 +329,7 @@ private void updateSettings(MethodCall methodCall, Result result) { } @TargetApi(Build.VERSION_CODES.KITKAT) - private void evaluateJavascript( + private void evaluateJavaScript( MethodCall methodCall, final Result result, final boolean returnValue) { String jsString = (String) methodCall.arguments; if (jsString == null) { @@ -350,14 +350,14 @@ public void onReceiveValue(String value) { } @SuppressWarnings("unchecked") - private void addJavascriptChannels(MethodCall methodCall, Result result) { + private void addJavaScriptChannels(MethodCall methodCall, Result result) { List channelNames = (List) methodCall.arguments; - registerJavascriptChannelNames(channelNames); + registerJavaScriptChannelNames(channelNames); result.success(null); } @SuppressWarnings("unchecked") - private void removeJavascriptChannels(MethodCall methodCall, Result result) { + private void removeJavaScriptChannels(MethodCall methodCall, Result result) { List channelNames = (List) methodCall.arguments; for (String channelName : channelNames) { webView.removeJavascriptInterface(channelName); @@ -465,10 +465,10 @@ private void updateAutoMediaPlaybackPolicy(int mode) { } } - private void registerJavascriptChannelNames(List channelNames) { + private void registerJavaScriptChannelNames(List channelNames) { for (String channelName : channelNames) { webView.addJavascriptInterface( - new JavascriptChannel(methodChannel, channelName, platformThreadHandler), channelName); + new JavaScriptChannel(methodChannel, channelName, platformThreadHandler), channelName); } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java index 918d7cc42a20..4d596351b3d0 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/JavaScriptChannel.java @@ -17,21 +17,21 @@ *

Exposes a single method named `postMessage` to JavaScript, which sends a message over a method * channel to the Dart code. */ -class JavascriptChannel { +class JavaScriptChannel { private final MethodChannel methodChannel; - private final String javascriptChannelName; + private final String javaScriptChannelName; private final Handler platformThreadHandler; /** * @param methodChannel the Flutter WebView method channel to which JS messages are sent - * @param javascriptChannelName the name of the JavaScript channel, this is sent over the method + * @param javaScriptChannelName the name of the JavaScript channel, this is sent over the method * channel with each message to let the Dart code know which JavaScript channel the message * was sent through */ - JavascriptChannel( - MethodChannel methodChannel, String javascriptChannelName, Handler platformThreadHandler) { + JavaScriptChannel( + MethodChannel methodChannel, String javaScriptChannelName, Handler platformThreadHandler) { this.methodChannel = methodChannel; - this.javascriptChannelName = javascriptChannelName; + this.javaScriptChannelName = javaScriptChannelName; this.platformThreadHandler = platformThreadHandler; } @@ -44,7 +44,7 @@ public void postMessage(final String message) { @Override public void run() { HashMap arguments = new HashMap<>(); - arguments.put("channel", javascriptChannelName); + arguments.put("channel", javaScriptChannelName); arguments.put("message", message); methodChannel.invokeMethod("javascriptChannelMessage", arguments); } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java index 0354ad66d7e3..8e3cdca5abe7 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java @@ -72,7 +72,7 @@ public void createWebView_shouldCreateWebViewWithDefaultConfiguration() { } @Test(expected = UnsupportedOperationException.class) - public void evaluateJavascript_shouldThrowForNullString() { + public void evaluateJavaScript_shouldThrowForNullString() { try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { // Setup mockedFlutterWebView @@ -97,7 +97,7 @@ public void apply() throws Throwable { } @Test - public void evaluateJavascript_shouldReturnValueOnSuccessForReturnValue() { + public void evaluateJavaScript_shouldReturnValueOnSuccessForReturnValue() { try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { // Setup mockedFlutterWebView @@ -130,7 +130,7 @@ public void evaluateJavascript_shouldReturnValueOnSuccessForReturnValue() { } @Test - public void evaluateJavascript_shouldReturnNilOnSuccessForNoReturnValue() { + public void evaluateJavaScript_shouldReturnNilOnSuccessForNoReturnValue() { try (MockedStatic mockedFlutterWebView = mockStatic(FlutterWebView.class)) { // Setup mockedFlutterWebView diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index 74da9ea413d6..83b564b2cef6 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -975,7 +975,7 @@ void main() { final WebViewController controller = await controllerCompleter.future; await pageLoaded.future; - final String viewportRectJSON = await _runJavascriptReturningResult( + final String viewportRectJSON = await _runJavaScriptReturningResult( controller, 'JSON.stringify(viewport.getBoundingClientRect())'); final Map viewportRectRelativeToViewport = jsonDecode(viewportRectJSON); @@ -983,7 +983,7 @@ void main() { // Check that the input is originally outside of the viewport. final String initialInputClientRectJSON = - await _runJavascriptReturningResult( + await _runJavaScriptReturningResult( controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); final Map initialInputClientRectRelativeToViewport = jsonDecode(initialInputClientRectJSON); @@ -998,7 +998,7 @@ void main() { // Check that focusing the input brought it into view. final String lastInputClientRectJSON = - await _runJavascriptReturningResult( + await _runJavaScriptReturningResult( controller, 'JSON.stringify(inputEl.getBoundingClientRect())'); final Map lastInputClientRectRelativeToViewport = jsonDecode(lastInputClientRectJSON); @@ -1408,10 +1408,10 @@ String _webviewBool(bool value) { /// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests. Future _getUserAgent(WebViewController controller) async { - return _runJavascriptReturningResult(controller, 'navigator.userAgent;'); + return _runJavaScriptReturningResult(controller, 'navigator.userAgent;'); } -Future _runJavascriptReturningResult( +Future _runJavaScriptReturningResult( WebViewController controller, String js) async { return jsonDecode(await controller.runJavascriptReturningResult(js)); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 4f4fdd9fb4cc..e5d4cd66525a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -5,7 +5,7 @@ #import "FlutterWebView.h" #import "FLTWKNavigationDelegate.h" #import "FLTWKProgressionDelegate.h" -#import "JavascriptChannelHandler.h" +#import "JavaScriptChannelHandler.h" @implementation FLTWebViewFactory { NSObject* _messenger; @@ -63,7 +63,7 @@ @implementation FLTWebViewController { FlutterMethodChannel* _channel; NSString* _currentUrl; // The set of registered JavaScript channel names. - NSMutableSet* _javascriptChannelNames; + NSMutableSet* _javaScriptChannelNames; FLTWKNavigationDelegate* _navigationDelegate; FLTWKProgressionDelegate* _progressionDelegate; } @@ -77,13 +77,13 @@ - (instancetype)initWithFrame:(CGRect)frame NSString* channelName = [NSString stringWithFormat:@"plugins.flutter.io/webview_%lld", viewId]; _channel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:messenger]; - _javascriptChannelNames = [[NSMutableSet alloc] init]; + _javaScriptChannelNames = [[NSMutableSet alloc] init]; WKUserContentController* userContentController = [[WKUserContentController alloc] init]; if ([args[@"javascriptChannelNames"] isKindOfClass:[NSArray class]]) { NSArray* javaScriptChannelNames = args[@"javascriptChannelNames"]; - [_javascriptChannelNames addObjectsFromArray:javaScriptChannelNames]; - [self registerJavascriptChannels:_javascriptChannelNames controller:userContentController]; + [_javaScriptChannelNames addObjectsFromArray:javaScriptChannelNames]; + [self registerJavaScriptChannels:_javaScriptChannelNames controller:userContentController]; } NSDictionary* settings = args[@"settings"]; @@ -156,9 +156,9 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if ([[call method] isEqualToString:@"runJavascriptReturningResult"]) { [self onRunJavascriptReturningResult:call result:result]; } else if ([[call method] isEqualToString:@"addJavascriptChannels"]) { - [self onAddJavascriptChannels:call result:result]; + [self onAddJavaScriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"removeJavascriptChannels"]) { - [self onRemoveJavascriptChannels:call result:result]; + [self onRemoveJavaScriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"clearCache"]) { [self clearCache:result]; } else if ([[call method] isEqualToString:@"getTitle"]) { @@ -229,7 +229,7 @@ - (void)onCurrentUrl:(FlutterMethodCall*)call result:(FlutterResult)result { - (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* jsString = [call arguments]; if (!jsString) { - result([FlutterError errorWithCode:@"evaluateJavascript_failed" + result([FlutterError errorWithCode:@"evaluateJavaScript_failed" message:@"JavaScript String cannot be null" details:nil]); return; @@ -238,7 +238,7 @@ - (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)resu completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error) { result([FlutterError - errorWithCode:@"evaluateJavascript_failed" + errorWithCode:@"evaluateJavaScript_failed" message:@"Failed evaluating JavaScript" details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", jsString, error]]); @@ -248,7 +248,9 @@ - (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)resu }]; } -- (void)onRunJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onRunJavascript:(FlutterMethodCall*)call + result:(FlutterResult)result + sendReturnValue:(BOOL)sendReturnValue { NSString* jsString = [call arguments]; if (!jsString) { result([FlutterError errorWithCode:@"runJavascript_failed" @@ -258,17 +260,20 @@ - (void)onRunJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { } [_webView evaluateJavaScript:jsString completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { - BOOL unsupportedTypeError = false; - if (@available(iOS 9, *)) { - unsupportedTypeError = - error && error.code == WKErrorJavaScriptResultTypeIsUnsupported; + if (error) { + if (sendReturnValue || (!sendReturnValue && error.code != WKErrorJavaScriptResultTypeIsUnsupported)) { + result([FlutterError + errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" + : @"runJavascript_failed") + message:@"Failed running JavaScript" + details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", + jsString, error]]); + } else { + result(nil); + } } - if (error && !unsupportedTypeError) { - result([FlutterError - errorWithCode:@"runJavascript_failed" - message:@"Failed running JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", - jsString, error]]); + if (sendReturnValue) { + result([NSString stringWithFormat:@"%@", evaluateResult]); } else { result(nil); } @@ -284,42 +289,34 @@ - (void)onRunJavascriptReturningResult:(FlutterMethodCall*)call result:(FlutterR return; } [_webView evaluateJavaScript:jsString - completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { - if (error) { - result([FlutterError - errorWithCode:@"runJavascriptReturningResult_failed" - message:@"Failed running JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", - jsString, error]]); - } else { - result([NSString stringWithFormat:@"%@", evaluateResult]); - } + completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error){ + }]; } -- (void)onAddJavascriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { NSArray* channelNames = [call arguments]; NSSet* channelNamesSet = [[NSSet alloc] initWithArray:channelNames]; - [_javascriptChannelNames addObjectsFromArray:channelNames]; - [self registerJavascriptChannels:channelNamesSet + [_javaScriptChannelNames addObjectsFromArray:channelNames]; + [self registerJavaScriptChannels:channelNamesSet controller:_webView.configuration.userContentController]; result(nil); } -- (void)onRemoveJavascriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onRemoveJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { // WkWebView does not support removing a single user script, so instead we remove all // user scripts, all message handlers. And re-register channels that shouldn't be removed. [_webView.configuration.userContentController removeAllUserScripts]; - for (NSString* channelName in _javascriptChannelNames) { + for (NSString* channelName in _javaScriptChannelNames) { [_webView.configuration.userContentController removeScriptMessageHandlerForName:channelName]; } NSArray* channelNamesToRemove = [call arguments]; for (NSString* channelName in channelNamesToRemove) { - [_javascriptChannelNames removeObject:channelName]; + [_javaScriptChannelNames removeObject:channelName]; } - [self registerJavascriptChannels:_javascriptChannelNames + [self registerJavaScriptChannels:_javaScriptChannelNames controller:_webView.configuration.userContentController]; result(nil); } @@ -503,11 +500,11 @@ - (bool)loadUrl:(NSString*)url withHeaders:(NSDictionary*) return true; } -- (void)registerJavascriptChannels:(NSSet*)channelNames +- (void)registerJavaScriptChannels:(NSSet*)channelNames controller:(WKUserContentController*)userContentController { for (NSString* channelName in channelNames) { - FLTJavascriptChannel* channel = - [[FLTJavascriptChannel alloc] initWithMethodChannel:_channel + FLTJavaScriptChannel* channel = + [[FLTJavaScriptChannel alloc] initWithMethodChannel:_channel javascriptChannelName:channelName]; [userContentController addScriptMessageHandler:channel name:channelName]; NSString* wrapperSource = [NSString diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h similarity index 70% rename from packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.h rename to packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h index dedadb4c8fb1..1732bf216c68 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h @@ -7,10 +7,10 @@ NS_ASSUME_NONNULL_BEGIN -@interface FLTJavascriptChannel : NSObject +@interface FLTJavaScriptChannelFLTJavaScriptChannel : NSObject - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - javascriptChannelName:(NSString*)javascriptChannelName; + javaScriptChannelName:(NSString*)javaScriptChannelName; @end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m similarity index 72% rename from packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m rename to packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m index 8bd8cea26f0e..2701acacf03b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavascriptChannelHandler.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m @@ -2,21 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "JavascriptChannelHandler.h" +#import "JavaScriptChannelHandler.h" -@implementation FLTJavascriptChannel { +@implementation FLTJavaScriptChannel { FlutterMethodChannel* _methodChannel; - NSString* _javascriptChannelName; + NSString* _javaScriptChannelName; } - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - javascriptChannelName:(NSString*)javascriptChannelName { + javaScriptChannelName:(NSString*)javaScriptChannelName { self = [super init]; NSAssert(methodChannel != nil, @"methodChannel must not be null."); - NSAssert(javascriptChannelName != nil, @"javascriptChannelName must not be null."); + NSAssert(javaScriptChannelName != nil, @"javascriptChannelName must not be null."); if (self) { _methodChannel = methodChannel; - _javascriptChannelName = javascriptChannelName; + _javaScriptChannelName = javaScriptChannelName; } return self; } @@ -24,10 +24,10 @@ - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel - (void)userContentController:(WKUserContentController*)userContentController didReceiveScriptMessage:(WKScriptMessage*)message { NSAssert(_methodChannel != nil, @"Can't send a message to an unitialized JavaScript channel."); - NSAssert(_javascriptChannelName != nil, + NSAssert(_javaScriptChannelName != nil, @"Can't send a message to an unitialized JavaScript channel."); NSDictionary* arguments = @{ - @"channel" : _javascriptChannelName, + @"channel" : _javaScriptChannelName, @"message" : [NSString stringWithFormat:@"%@", message.body] }; [_methodChannel invokeMethod:@"javascriptChannelMessage" arguments:arguments]; From 527bd67aeb89aad9cbaff58b266abbde4d5e41cd Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:16:20 +0200 Subject: [PATCH 20/36] Partially implement PR feedback --- .../ios/Classes/FlutterWebView.m | 21 ++++--------------- .../ios/Classes/JavaScriptChannelHandler.h | 2 +- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index e5d4cd66525a..1d96b7074710 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -152,9 +152,9 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if ([[call method] isEqualToString:@"evaluateJavascript"]) { [self onEvaluateJavascript:call result:result]; } else if ([[call method] isEqualToString:@"runJavascript"]) { - [self onRunJavascript:call result:result]; + [self onRunJavascript:call result:result sendReturnValue:false]; } else if ([[call method] isEqualToString:@"runJavascriptReturningResult"]) { - [self onRunJavascriptReturningResult:call result:result]; + [self onRunJavascript:call result:result sendReturnValue:true]; } else if ([[call method] isEqualToString:@"addJavascriptChannels"]) { [self onAddJavaScriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"removeJavascriptChannels"]) { @@ -271,6 +271,7 @@ - (void)onRunJavascript:(FlutterMethodCall*)call } else { result(nil); } + return; } if (sendReturnValue) { result([NSString stringWithFormat:@"%@", evaluateResult]); @@ -280,20 +281,6 @@ - (void)onRunJavascript:(FlutterMethodCall*)call }]; } -- (void)onRunJavascriptReturningResult:(FlutterMethodCall*)call result:(FlutterResult)result { - NSString* jsString = [call arguments]; - if (!jsString) { - result([FlutterError errorWithCode:@"runJavascriptReturningResult_failed" - message:@"JavaScript String cannot be null" - details:nil]); - return; - } - [_webView evaluateJavaScript:jsString - completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error){ - - }]; -} - - (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { NSArray* channelNames = [call arguments]; NSSet* channelNamesSet = [[NSSet alloc] initWithArray:channelNames]; @@ -505,7 +492,7 @@ - (void)registerJavaScriptChannels:(NSSet*)channelNames for (NSString* channelName in channelNames) { FLTJavaScriptChannel* channel = [[FLTJavaScriptChannel alloc] initWithMethodChannel:_channel - javascriptChannelName:channelName]; + javaScriptChannelName:channelName]; [userContentController addScriptMessageHandler:channel name:channelName]; NSString* wrapperSource = [NSString stringWithFormat:@"window.%@ = webkit.messageHandlers.%@;", channelName, channelName]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h index 1732bf216c68..a0a5ec657295 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface FLTJavaScriptChannelFLTJavaScriptChannel : NSObject +@interface FLTJavaScriptChannel : NSObject - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel javaScriptChannelName:(NSString*)javaScriptChannelName; From acf5ff98e113858b99491850961c5eee09884a96 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:18:47 +0200 Subject: [PATCH 21/36] Format --- .../webview_flutter_wkwebview/ios/Classes/FlutterWebView.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 1d96b7074710..355388310203 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -261,7 +261,8 @@ - (void)onRunJavascript:(FlutterMethodCall*)call [_webView evaluateJavaScript:jsString completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error) { - if (sendReturnValue || (!sendReturnValue && error.code != WKErrorJavaScriptResultTypeIsUnsupported)) { + if (sendReturnValue || + (!sendReturnValue && error.code != WKErrorJavaScriptResultTypeIsUnsupported)) { result([FlutterError errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" : @"runJavascript_failed") @@ -271,7 +272,7 @@ - (void)onRunJavascript:(FlutterMethodCall*)call } else { result(nil); } - return; + return; } if (sendReturnValue) { result([NSString stringWithFormat:@"%@", evaluateResult]); From aed3830934f2b4f4062dc55d05dec33799b2cd92 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:34:21 +0200 Subject: [PATCH 22/36] Update podfile --- .../webview_flutter_wkwebview/example/ios/Podfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile index 66509fcae284..311e8c9710f0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +platform :ios, '9.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' From 6967c4ff143ea3edaf43b1217421fc8cd57d83f5 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:42:38 +0200 Subject: [PATCH 23/36] Update podfile --- packages/webview_flutter/webview_flutter/example/ios/Podfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter/example/ios/Podfile b/packages/webview_flutter/webview_flutter/example/ios/Podfile index 66509fcae284..311e8c9710f0 100644 --- a/packages/webview_flutter/webview_flutter/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '9.0' +platform :ios, '9.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' From 37ba26ef679b48bda3564fe37321dfe6f8c06a92 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:49:05 +0200 Subject: [PATCH 24/36] Update podfiles --- packages/webview_flutter/webview_flutter/example/ios/Podfile | 3 +++ .../webview_flutter_wkwebview/example/ios/Podfile | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packages/webview_flutter/webview_flutter/example/ios/Podfile b/packages/webview_flutter/webview_flutter/example/ios/Podfile index 311e8c9710f0..26e73e6cd38f 100644 --- a/packages/webview_flutter/webview_flutter/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter/example/ios/Podfile @@ -41,5 +41,8 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' + end end end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile index 311e8c9710f0..26e73e6cd38f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile @@ -41,5 +41,8 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' + end end end From 13076bac05889fcf0010f5b306a2064683be4cce Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 13:58:55 +0200 Subject: [PATCH 25/36] Update iOS project files --- .../ios/Runner.xcodeproj/project.pbxproj | 97 +++++++++-------- .../ios/Runner.xcodeproj/project.pbxproj | 103 +++++++++--------- 2 files changed, 105 insertions(+), 95 deletions(-) diff --git a/packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/project.pbxproj index 62428d041adf..0759b31a2f25 100644 --- a/packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/project.pbxproj @@ -11,13 +11,13 @@ 334734012669319100DCC49E /* FLTWebViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 68BDCAF523C3F97800D9C032 /* FLTWebViewTests.m */; }; 334734022669319400DCC49E /* FLTWKNavigationDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 686B4BF82548DBC7000AEA36 /* FLTWKNavigationDelegateTests.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 63D2F2FB307F1F037702C198 /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BEC8CD326B252E47ABE6C037 /* libPods-RunnerTests.a */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 9D26F6F82D91F92CC095EBA9 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B845D8FBDE0AAD6BE1A0386 /* libPods-Runner.a */; }; - D9A9D48F1A75E5C682944DDD /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27CC950C9005575711528C12 /* libPods-RunnerTests.a */; }; + E6159E2B6496F35B1D4F4096 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0ABA59F25635F077C9EA161 /* libPods-Runner.a */; }; F7151F77266057800028CB91 /* FLTWebViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = F7151F76266057800028CB91 /* FLTWebViewUITests.m */; }; /* End PBXBuildFile section */ @@ -52,11 +52,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 127772EEA7782174BE0D74B5 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 11DF059E983DF25F078B44CC /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 27CC950C9005575711528C12 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3CEFE8F0E91B9792E4EE427B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 4D2B3F45D8E6CA81EA52591E /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 5D19D984A61169BB95DB0FED /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 686B4BF82548DBC7000AEA36 /* FLTWKNavigationDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTWKNavigationDelegateTests.m; sourceTree = ""; }; 68BDCAE923C3F7CB00D9C032 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 68BDCAED23C3F7CB00D9C032 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -64,7 +66,6 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 8B845D8FBDE0AAD6BE1A0386 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -73,9 +74,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C475C484BD510DD9CB2E403C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - E14113434CCE6D3186B5CBC3 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - F674B2A05DAC369B4FF27850 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + BEC8CD326B252E47ABE6C037 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + C0ABA59F25635F077C9EA161 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; F7151F74266057800028CB91 /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; F7151F76266057800028CB91 /* FLTWebViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTWebViewUITests.m; sourceTree = ""; }; F7151F78266057800028CB91 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -86,7 +86,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D9A9D48F1A75E5C682944DDD /* libPods-RunnerTests.a in Frameworks */, + 63D2F2FB307F1F037702C198 /* libPods-RunnerTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -94,7 +94,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9D26F6F82D91F92CC095EBA9 /* libPods-Runner.a in Frameworks */, + E6159E2B6496F35B1D4F4096 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -108,6 +108,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 00D2395F7DDFEE571DF3C0B1 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C0ABA59F25635F077C9EA161 /* libPods-Runner.a */, + BEC8CD326B252E47ABE6C037 /* libPods-RunnerTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 68BDCAEA23C3F7CB00D9C032 /* RunnerTests */ = { isa = PBXGroup; children = ( @@ -137,8 +146,8 @@ 68BDCAEA23C3F7CB00D9C032 /* RunnerTests */, F7151F75266057800028CB91 /* RunnerUITests */, 97C146EF1CF9000F007C117D /* Products */, - C6FFB52F5C2B8A41A7E39DE2 /* Pods */, - B6736FC417BDCCDA377E779D /* Frameworks */, + EA36D6F90B795550E32A139A /* Pods */, + 00D2395F7DDFEE571DF3C0B1 /* Frameworks */, ); sourceTree = ""; }; @@ -176,24 +185,16 @@ name = "Supporting Files"; sourceTree = ""; }; - B6736FC417BDCCDA377E779D /* Frameworks */ = { - isa = PBXGroup; - children = ( - 8B845D8FBDE0AAD6BE1A0386 /* libPods-Runner.a */, - 27CC950C9005575711528C12 /* libPods-RunnerTests.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - C6FFB52F5C2B8A41A7E39DE2 /* Pods */ = { + EA36D6F90B795550E32A139A /* Pods */ = { isa = PBXGroup; children = ( - 127772EEA7782174BE0D74B5 /* Pods-Runner.debug.xcconfig */, - C475C484BD510DD9CB2E403C /* Pods-Runner.release.xcconfig */, - F674B2A05DAC369B4FF27850 /* Pods-RunnerTests.debug.xcconfig */, - E14113434CCE6D3186B5CBC3 /* Pods-RunnerTests.release.xcconfig */, + 4D2B3F45D8E6CA81EA52591E /* Pods-Runner.debug.xcconfig */, + 11DF059E983DF25F078B44CC /* Pods-Runner.release.xcconfig */, + 3CEFE8F0E91B9792E4EE427B /* Pods-RunnerTests.debug.xcconfig */, + 5D19D984A61169BB95DB0FED /* Pods-RunnerTests.release.xcconfig */, ); name = Pods; + path = Pods; sourceTree = ""; }; F7151F75266057800028CB91 /* RunnerUITests */ = { @@ -212,7 +213,7 @@ isa = PBXNativeTarget; buildConfigurationList = 68BDCAF223C3F7CB00D9C032 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 53FD4CBDD9756D74B5A3B4C1 /* [CP] Check Pods Manifest.lock */, + EA0C9BB56C9A98B4F095051B /* [CP] Check Pods Manifest.lock */, 68BDCAE523C3F7CB00D9C032 /* Sources */, 68BDCAE623C3F7CB00D9C032 /* Frameworks */, 68BDCAE723C3F7CB00D9C032 /* Resources */, @@ -231,7 +232,7 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - B71376B4FB8384EF9D5F3F84 /* [CP] Check Pods Manifest.lock */, + 1B3EA6BF26F6D525A8503093 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -338,41 +339,41 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + 1B3EA6BF26F6D525A8503093 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Thin Binary"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed\n/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 53FD4CBDD9756D74B5A3B4C1 /* [CP] Check Pods Manifest.lock */ = { + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Thin Binary"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed\n/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin\n"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -388,18 +389,22 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; - B71376B4FB8384EF9D5F3F84 /* [CP] Check Pods Manifest.lock */ = { + EA0C9BB56C9A98B4F095051B /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -473,7 +478,7 @@ /* Begin XCBuildConfiguration section */ 68BDCAF023C3F7CB00D9C032 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F674B2A05DAC369B4FF27850 /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = 3CEFE8F0E91B9792E4EE427B /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -487,7 +492,7 @@ }; 68BDCAF123C3F7CB00D9C032 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E14113434CCE6D3186B5CBC3 /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = 5D19D984A61169BB95DB0FED /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 62428d041adf..ba0deb4781d4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -16,8 +16,8 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 9D26F6F82D91F92CC095EBA9 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B845D8FBDE0AAD6BE1A0386 /* libPods-Runner.a */; }; - D9A9D48F1A75E5C682944DDD /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 27CC950C9005575711528C12 /* libPods-RunnerTests.a */; }; + AE8C124DC8CA68E4D9B30EAB /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 528CB85D53C983D2C5DAFDC5 /* libPods-RunnerTests.a */; }; + DAF0E91266956134538CC667 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 572FFC2B2BA326B420B22679 /* libPods-Runner.a */; }; F7151F77266057800028CB91 /* FLTWebViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = F7151F76266057800028CB91 /* FLTWebViewUITests.m */; }; /* End PBXBuildFile section */ @@ -52,11 +52,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 127772EEA7782174BE0D74B5 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 27CC950C9005575711528C12 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 528CB85D53C983D2C5DAFDC5 /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 572FFC2B2BA326B420B22679 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5C776D27D0DDA247ED5EA72B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 686B4BF82548DBC7000AEA36 /* FLTWKNavigationDelegateTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTWKNavigationDelegateTests.m; sourceTree = ""; }; 68BDCAE923C3F7CB00D9C032 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 68BDCAED23C3F7CB00D9C032 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -64,7 +65,6 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 8B845D8FBDE0AAD6BE1A0386 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -73,12 +73,12 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C475C484BD510DD9CB2E403C /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - E14113434CCE6D3186B5CBC3 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - F674B2A05DAC369B4FF27850 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + B89AA31A64040E4A2F1E0CAF /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + C370F140C3A19241FD8C5E64 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; F7151F74266057800028CB91 /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; F7151F76266057800028CB91 /* FLTWebViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTWebViewUITests.m; sourceTree = ""; }; F7151F78266057800028CB91 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + F7A1921261392D1CBDAEC2E8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -86,7 +86,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D9A9D48F1A75E5C682944DDD /* libPods-RunnerTests.a in Frameworks */, + AE8C124DC8CA68E4D9B30EAB /* libPods-RunnerTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -94,7 +94,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9D26F6F82D91F92CC095EBA9 /* libPods-Runner.a in Frameworks */, + DAF0E91266956134538CC667 /* libPods-Runner.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -108,6 +108,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 52FBC2B567345431F81A0A0F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 572FFC2B2BA326B420B22679 /* libPods-Runner.a */, + 528CB85D53C983D2C5DAFDC5 /* libPods-RunnerTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; 68BDCAEA23C3F7CB00D9C032 /* RunnerTests */ = { isa = PBXGroup; children = ( @@ -137,8 +146,8 @@ 68BDCAEA23C3F7CB00D9C032 /* RunnerTests */, F7151F75266057800028CB91 /* RunnerUITests */, 97C146EF1CF9000F007C117D /* Products */, - C6FFB52F5C2B8A41A7E39DE2 /* Pods */, - B6736FC417BDCCDA377E779D /* Frameworks */, + B8AEEA11D6ECBD09750349AE /* Pods */, + 52FBC2B567345431F81A0A0F /* Frameworks */, ); sourceTree = ""; }; @@ -176,24 +185,16 @@ name = "Supporting Files"; sourceTree = ""; }; - B6736FC417BDCCDA377E779D /* Frameworks */ = { + B8AEEA11D6ECBD09750349AE /* Pods */ = { isa = PBXGroup; children = ( - 8B845D8FBDE0AAD6BE1A0386 /* libPods-Runner.a */, - 27CC950C9005575711528C12 /* libPods-RunnerTests.a */, - ); - name = Frameworks; - sourceTree = ""; - }; - C6FFB52F5C2B8A41A7E39DE2 /* Pods */ = { - isa = PBXGroup; - children = ( - 127772EEA7782174BE0D74B5 /* Pods-Runner.debug.xcconfig */, - C475C484BD510DD9CB2E403C /* Pods-Runner.release.xcconfig */, - F674B2A05DAC369B4FF27850 /* Pods-RunnerTests.debug.xcconfig */, - E14113434CCE6D3186B5CBC3 /* Pods-RunnerTests.release.xcconfig */, + F7A1921261392D1CBDAEC2E8 /* Pods-Runner.debug.xcconfig */, + B89AA31A64040E4A2F1E0CAF /* Pods-Runner.release.xcconfig */, + C370F140C3A19241FD8C5E64 /* Pods-RunnerTests.debug.xcconfig */, + 5C776D27D0DDA247ED5EA72B /* Pods-RunnerTests.release.xcconfig */, ); name = Pods; + path = Pods; sourceTree = ""; }; F7151F75266057800028CB91 /* RunnerUITests */ = { @@ -212,7 +213,7 @@ isa = PBXNativeTarget; buildConfigurationList = 68BDCAF223C3F7CB00D9C032 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 53FD4CBDD9756D74B5A3B4C1 /* [CP] Check Pods Manifest.lock */, + 0067CEC0658A36CBFF8074E7 /* [CP] Check Pods Manifest.lock */, 68BDCAE523C3F7CB00D9C032 /* Sources */, 68BDCAE623C3F7CB00D9C032 /* Frameworks */, 68BDCAE723C3F7CB00D9C032 /* Resources */, @@ -231,7 +232,7 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - B71376B4FB8384EF9D5F3F84 /* [CP] Check Pods Manifest.lock */, + 6F536C27DD48B395A30EBB65 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -338,21 +339,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed\n/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin\n"; - }; - 53FD4CBDD9756D74B5A3B4C1 /* [CP] Check Pods Manifest.lock */ = { + 0067CEC0658A36CBFF8074E7 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -374,30 +361,34 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 9740EEB61CF901F6004384FC /* Run Script */ = { + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Run Script"; + name = "Thin Binary"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed\n/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin\n"; }; - B71376B4FB8384EF9D5F3F84 /* [CP] Check Pods Manifest.lock */ = { + 6F536C27DD48B395A30EBB65 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); @@ -406,6 +397,20 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -473,7 +478,7 @@ /* Begin XCBuildConfiguration section */ 68BDCAF023C3F7CB00D9C032 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F674B2A05DAC369B4FF27850 /* Pods-RunnerTests.debug.xcconfig */; + baseConfigurationReference = C370F140C3A19241FD8C5E64 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -487,7 +492,7 @@ }; 68BDCAF123C3F7CB00D9C032 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = E14113434CCE6D3186B5CBC3 /* Pods-RunnerTests.release.xcconfig */; + baseConfigurationReference = 5C776D27D0DDA247ED5EA72B /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; From 0c87362fac2e2450875e17d3abaf66923fadb02c Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 14:11:57 +0200 Subject: [PATCH 26/36] Update podspec --- .../ios/webview_flutter_wkwebview.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/webview_flutter_wkwebview.podspec b/packages/webview_flutter/webview_flutter_wkwebview/ios/webview_flutter_wkwebview.podspec index 37905f147489..2dfb336df35a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/webview_flutter_wkwebview.podspec +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/webview_flutter_wkwebview.podspec @@ -18,6 +18,6 @@ Downloaded by pub (not CocoaPods). s.public_header_files = 'Classes/**/*.h' s.dependency 'Flutter' - s.platform = :ios, '8.0' + s.platform = :ios, '9.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } end From 962ad0236ac76a98b47e31aa3cc0b9aa3f36a96a Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 14:13:29 +0200 Subject: [PATCH 27/36] Remove unnecessary podfile configuration --- packages/webview_flutter/webview_flutter/example/ios/Podfile | 3 --- .../webview_flutter_wkwebview/example/ios/Podfile | 3 --- 2 files changed, 6 deletions(-) diff --git a/packages/webview_flutter/webview_flutter/example/ios/Podfile b/packages/webview_flutter/webview_flutter/example/ios/Podfile index 26e73e6cd38f..311e8c9710f0 100644 --- a/packages/webview_flutter/webview_flutter/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter/example/ios/Podfile @@ -41,8 +41,5 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) - target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' - end end end diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile index 26e73e6cd38f..311e8c9710f0 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile @@ -41,8 +41,5 @@ end post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) - target.build_configurations.each do |config| - config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' - end end end From 9184d48a324786ecd04da6c014afb4e179f8c77e Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 8 Oct 2021 14:22:56 +0200 Subject: [PATCH 28/36] Implemented PR feedback --- .../ios/Classes/FlutterWebView.m | 10 +++++----- .../ios/Classes/JavaScriptChannelHandler.m | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 355388310203..523abbc9999f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -150,11 +150,11 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if ([[call method] isEqualToString:@"currentUrl"]) { [self onCurrentUrl:call result:result]; } else if ([[call method] isEqualToString:@"evaluateJavascript"]) { - [self onEvaluateJavascript:call result:result]; + [self onEvaluateJavaScript:call result:result]; } else if ([[call method] isEqualToString:@"runJavascript"]) { - [self onRunJavascript:call result:result sendReturnValue:false]; + [self onRunJavaScript:call result:result sendReturnValue:false]; } else if ([[call method] isEqualToString:@"runJavascriptReturningResult"]) { - [self onRunJavascript:call result:result sendReturnValue:true]; + [self onRunJavaScript:call result:result sendReturnValue:true]; } else if ([[call method] isEqualToString:@"addJavascriptChannels"]) { [self onAddJavaScriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"removeJavascriptChannels"]) { @@ -226,7 +226,7 @@ - (void)onCurrentUrl:(FlutterMethodCall*)call result:(FlutterResult)result { result(_currentUrl); } -- (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)result { +- (void)onEvaluateJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result { NSString* jsString = [call arguments]; if (!jsString) { result([FlutterError errorWithCode:@"evaluateJavaScript_failed" @@ -248,7 +248,7 @@ - (void)onEvaluateJavascript:(FlutterMethodCall*)call result:(FlutterResult)resu }]; } -- (void)onRunJavascript:(FlutterMethodCall*)call +- (void)onRunJavaScript:(FlutterMethodCall*)call result:(FlutterResult)result sendReturnValue:(BOOL)sendReturnValue { NSString* jsString = [call arguments]; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m index 2701acacf03b..ec9a363a4b2e 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/JavaScriptChannelHandler.m @@ -13,7 +13,7 @@ - (instancetype)initWithMethodChannel:(FlutterMethodChannel*)methodChannel javaScriptChannelName:(NSString*)javaScriptChannelName { self = [super init]; NSAssert(methodChannel != nil, @"methodChannel must not be null."); - NSAssert(javaScriptChannelName != nil, @"javascriptChannelName must not be null."); + NSAssert(javaScriptChannelName != nil, @"javaScriptChannelName must not be null."); if (self) { _methodChannel = methodChannel; _javaScriptChannelName = javaScriptChannelName; From 80cbe9b0a8a10d844c2eb06b6566f10437207718 Mon Sep 17 00:00:00 2001 From: BeMacized Date: Mon, 18 Oct 2021 14:24:20 +0200 Subject: [PATCH 29/36] Format --- .../example/integration_test/webview_flutter_test.dart | 9 +++------ .../example/integration_test/webview_flutter_test.dart | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index 666d50ebcc14..8fc4e661e111 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -1062,8 +1062,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; - await controller - .runJavascript('location.href = "$secondaryUrl"'); + await controller.runJavascript('location.href = "$secondaryUrl"'); await pageLoads.stream.first; // Wait for the next page load. final String? currentUrl = await controller.currentUrl(); @@ -1229,8 +1228,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; - await controller - .runJavascript('location.href = "$secondaryUrl"'); + await controller.runJavascript('location.href = "$secondaryUrl"'); await pageLoads.stream.first; // Wait for second page to load. final String? currentUrl = await controller.currentUrl(); @@ -1285,8 +1283,7 @@ void main() { ), ); final WebViewController controller = await controllerCompleter.future; - await controller - .runJavascript('window.open("$primaryUrl", "_blank")'); + await controller.runJavascript('window.open("$primaryUrl", "_blank")'); await pageLoaded.future; final String? currentUrl = await controller.currentUrl(); expect(currentUrl, primaryUrl); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 9d63c75c3fad..a103f262e338 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -924,8 +924,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; - await controller - .runJavascript('location.href = "$secondaryUrl"'); + await controller.runJavascript('location.href = "$secondaryUrl"'); await pageLoads.stream.first; // Wait for the next page load. final String? currentUrl = await controller.currentUrl(); @@ -1096,8 +1095,7 @@ void main() { await pageLoads.stream.first; // Wait for initial page load. final WebViewController controller = await controllerCompleter.future; - await controller - .runJavascript('location.href = "$secondaryUrl"'); + await controller.runJavascript('location.href = "$secondaryUrl"'); await pageLoads.stream.first; // Wait for second page to load. final String? currentUrl = await controller.currentUrl(); @@ -1152,8 +1150,7 @@ void main() { ), ); final WebViewController controller = await controllerCompleter.future; - await controller - .runJavascript('window.open("$primaryUrl", "_blank")'); + await controller.runJavascript('window.open("$primaryUrl", "_blank")'); await pageLoaded.future; final String? currentUrl = await controller.currentUrl(); expect(currentUrl, primaryUrl); From 9fdab9dff6db8034f981055bc54f1d07b055cdbb Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 22 Oct 2021 11:01:39 +0200 Subject: [PATCH 30/36] Revert podfile changes --- packages/webview_flutter/webview_flutter/example/ios/Podfile | 2 +- .../webview_flutter_wkwebview/example/ios/Podfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter/example/ios/Podfile b/packages/webview_flutter/webview_flutter/example/ios/Podfile index 311e8c9710f0..66509fcae284 100644 --- a/packages/webview_flutter/webview_flutter/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '9.0' +# platform :ios, '9.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile index 311e8c9710f0..66509fcae284 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '9.0' +# platform :ios, '9.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' From 6e609d77ca78b0b8be8e9368692ea22a25ade3ad Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 22 Oct 2021 11:23:51 +0200 Subject: [PATCH 31/36] Implemented PR feedback --- .../webview_flutter_test.dart | 3 +- .../ios/Classes/FlutterWebView.m | 40 +++++++++---------- 2 files changed, 21 insertions(+), 22 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index a103f262e338..0b1d78cf3d5c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -158,8 +158,7 @@ void main() { // See: https://github.com/flutter/flutter/issues/66318#issuecomment-701105380 // TODO(cyanglaz): remove the workaround "1" in the end when the below issue is fixed. // https://github.com/flutter/flutter/issues/66318 - await controller - .runJavascriptReturningResult('Echo.postMessage("hello");1;'); + await controller.runJavascriptReturningResult('Echo.postMessage("hello");'); expect(messagesReceived, equals(['hello'])); }); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 523abbc9999f..89d0fc202b68 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -152,9 +152,9 @@ - (void)onMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { } else if ([[call method] isEqualToString:@"evaluateJavascript"]) { [self onEvaluateJavaScript:call result:result]; } else if ([[call method] isEqualToString:@"runJavascript"]) { - [self onRunJavaScript:call result:result sendReturnValue:false]; + [self onRunJavaScript:call result:result sendReturnValue:NO]; } else if ([[call method] isEqualToString:@"runJavascriptReturningResult"]) { - [self onRunJavaScript:call result:result sendReturnValue:true]; + [self onRunJavaScript:call result:result sendReturnValue:YES]; } else if ([[call method] isEqualToString:@"addJavascriptChannels"]) { [self onAddJavaScriptChannels:call result:result]; } else if ([[call method] isEqualToString:@"removeJavascriptChannels"]) { @@ -258,28 +258,28 @@ - (void)onRunJavaScript:(FlutterMethodCall*)call details:nil]); return; } - [_webView evaluateJavaScript:jsString - completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { - if (error) { - if (sendReturnValue || - (!sendReturnValue && error.code != WKErrorJavaScriptResultTypeIsUnsupported)) { - result([FlutterError + [_webView + evaluateJavaScript:jsString + completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { + if (error) { + // WebKit will throw an error (WKErrorJavaScriptResultTypeIsUnsupported) when the + // type of the evaluated value is unsupported. This also goes for `null` and `undefined`, + // for example when running a void function. For ease of use this specific error is + // ignored when no return value is expected. + BOOL sendError = sendReturnValue || error.code != WKErrorJavaScriptResultTypeIsUnsupported; + result( + sendError + ? [FlutterError errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" : @"runJavascript_failed") message:@"Failed running JavaScript" details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", - jsString, error]]); - } else { - result(nil); - } - return; - } - if (sendReturnValue) { - result([NSString stringWithFormat:@"%@", evaluateResult]); - } else { - result(nil); - } - }]; + jsString, error]] + : nil); + return; + } + result(sendReturnValue ? [NSString stringWithFormat:@"%@", evaluateResult] : nil); + }]; } - (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { From f6d8cb4959de63a7fffa10e4f7b55d26e0bf1655 Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 22 Oct 2021 11:45:09 +0200 Subject: [PATCH 32/36] Fix formatting --- .../ios/Classes/FlutterWebView.m | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index 89d0fc202b68..dc8c84155153 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -259,27 +259,28 @@ - (void)onRunJavaScript:(FlutterMethodCall*)call return; } [_webView - evaluateJavaScript:jsString - completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { - if (error) { - // WebKit will throw an error (WKErrorJavaScriptResultTypeIsUnsupported) when the - // type of the evaluated value is unsupported. This also goes for `null` and `undefined`, - // for example when running a void function. For ease of use this specific error is - // ignored when no return value is expected. - BOOL sendError = sendReturnValue || error.code != WKErrorJavaScriptResultTypeIsUnsupported; - result( - sendError - ? [FlutterError - errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" - : @"runJavascript_failed") - message:@"Failed running JavaScript" - details:[NSString stringWithFormat:@"JavaScript string was: '%@'\n%@", - jsString, error]] - : nil); - return; - } - result(sendReturnValue ? [NSString stringWithFormat:@"%@", evaluateResult] : nil); - }]; + evaluateJavaScript:jsString + completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { + if (error) { + // WebKit will throw an error (WKErrorJavaScriptResultTypeIsUnsupported) when the + // type of the evaluated value is unsupported. This also goes for `null` and `undefined`, + // for example when running a void function. For ease of use this specific error is + // ignored when no return value is expected. + BOOL sendError = + sendReturnValue || error.code != WKErrorJavaScriptResultTypeIsUnsupported; + result(sendError + ? [FlutterError + errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" + : @"runJavascript_failed") + message:@"Failed running JavaScript" + details:[NSString + stringWithFormat:@"JavaScript string was: '%@'\n%@", + jsString, error]] + : nil); + return; + } + result(sendReturnValue ? [NSString stringWithFormat:@"%@", evaluateResult] : nil); + }]; } - (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { From b019d3cfa717a021b9370d8e3649d93e8def371b Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 22 Oct 2021 11:52:21 +0200 Subject: [PATCH 33/36] Fix formatting --- .../ios/Classes/FlutterWebView.m | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index dc8c84155153..b8938a0f3271 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -259,28 +259,28 @@ - (void)onRunJavaScript:(FlutterMethodCall*)call return; } [_webView - evaluateJavaScript:jsString - completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { - if (error) { - // WebKit will throw an error (WKErrorJavaScriptResultTypeIsUnsupported) when the - // type of the evaluated value is unsupported. This also goes for `null` and `undefined`, - // for example when running a void function. For ease of use this specific error is - // ignored when no return value is expected. - BOOL sendError = - sendReturnValue || error.code != WKErrorJavaScriptResultTypeIsUnsupported; - result(sendError - ? [FlutterError - errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" - : @"runJavascript_failed") - message:@"Failed running JavaScript" - details:[NSString - stringWithFormat:@"JavaScript string was: '%@'\n%@", - jsString, error]] - : nil); - return; - } - result(sendReturnValue ? [NSString stringWithFormat:@"%@", evaluateResult] : nil); - }]; + evaluateJavaScript:jsString + completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { + if (error) { + // WebKit will throw an error (WKErrorJavaScriptResultTypeIsUnsupported) when the + // type of the evaluated value is unsupported. This also goes for `null` and `undefined`, + // for example when running a void function. For ease of use this specific error is + // ignored when no return value is expected. + BOOL sendError = + sendReturnValue || error.code != WKErrorJavaScriptResultTypeIsUnsupported; + result(sendError + ? [FlutterError + errorWithCode:(sendReturnValue ? @"runJavascriptReturningResult_failed" + : @"runJavascript_failed") + message:@"Failed running JavaScript" + details:[NSString + stringWithFormat:@"JavaScript string was: '%@'\n%@", + jsString, error]] + : nil); + return; + } + result(sendReturnValue ? [NSString stringWithFormat:@"%@", evaluateResult] : nil); + }]; } - (void)onAddJavaScriptChannels:(FlutterMethodCall*)call result:(FlutterResult)result { From 2b0f4909d02d3222e118d45b3d2dfb9e9a5b917b Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Fri, 22 Oct 2021 12:05:24 +0200 Subject: [PATCH 34/36] Fixed test. --- .../example/integration_test/webview_flutter_test.dart | 6 +----- .../webview_flutter_wkwebview/ios/Classes/FlutterWebView.m | 6 +++--- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 0b1d78cf3d5c..2451f2670030 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -154,11 +154,7 @@ void main() { await pageLoaded.future; expect(messagesReceived, isEmpty); - // Append a return value "1" in the end will prevent an iOS platform exception. - // See: https://github.com/flutter/flutter/issues/66318#issuecomment-701105380 - // TODO(cyanglaz): remove the workaround "1" in the end when the below issue is fixed. - // https://github.com/flutter/flutter/issues/66318 - await controller.runJavascriptReturningResult('Echo.postMessage("hello");'); + await controller.runJavascript('Echo.postMessage("hello");'); expect(messagesReceived, equals(['hello'])); }); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m index b8938a0f3271..9be5576b4ede 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m +++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m @@ -263,9 +263,9 @@ - (void)onRunJavaScript:(FlutterMethodCall*)call completionHandler:^(_Nullable id evaluateResult, NSError* _Nullable error) { if (error) { // WebKit will throw an error (WKErrorJavaScriptResultTypeIsUnsupported) when the - // type of the evaluated value is unsupported. This also goes for `null` and `undefined`, - // for example when running a void function. For ease of use this specific error is - // ignored when no return value is expected. + // type of the evaluated value is unsupported. This also goes for + // `null` and `undefined` on iOS 14+, for example when running a void function. + // For ease of use this specific error is ignored when no return value is expected. BOOL sendError = sendReturnValue || error.code != WKErrorJavaScriptResultTypeIsUnsupported; result(sendError From fa9526c8606df771e2cefa736e1ab305d592b6c0 Mon Sep 17 00:00:00 2001 From: BeMacized Date: Tue, 26 Oct 2021 13:24:53 +0200 Subject: [PATCH 35/36] Re-add integration tests for deprecated evaluateJavascript method. --- .../webview_flutter_test.dart | 21 +++++++++++++++++++ .../example/lib/web_view.dart | 10 +++++++++ .../webview_flutter_test.dart | 21 +++++++++++++++++++ .../example/lib/web_view.dart | 10 +++++++++ 4 files changed, 62 insertions(+) diff --git a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart index 8fc4e661e111..8e3dcb458ee8 100644 --- a/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_android/example/integration_test/webview_flutter_test.dart @@ -76,6 +76,27 @@ void main() { expect(currentUrl, secondaryUrl); }, skip: _skipDueToIssue86757); + testWidgets('evaluateJavascript', (WidgetTester tester) async { + final Completer controllerCompleter = + Completer(); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: WebView( + key: GlobalKey(), + initialUrl: primaryUrl, + onWebViewCreated: (WebViewController controller) { + controllerCompleter.complete(controller); + }, + javascriptMode: JavascriptMode.unrestricted, + ), + ), + ); + final WebViewController controller = await controllerCompleter.future; + final String result = await controller.evaluateJavascript('1 + 1'); + expect(result, equals('2')); + }); + // TODO(bparrishMines): skipped due to https://github.com/flutter/flutter/issues/86757. testWidgets('loadUrl with headers', (WidgetTester tester) async { final Completer controllerCompleter = diff --git a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart index 0f9eed75656d..7ae22f345839 100644 --- a/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_android/example/lib/web_view.dart @@ -481,6 +481,16 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } + @visibleForTesting + // ignore: public_member_api_docs + Future evaluateJavascript(String javascriptString) { + if (_settings.javascriptMode == JavascriptMode.disabled) { + return Future.error(FlutterError( + 'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.')); + } + return _webViewPlatformController.evaluateJavascript(javascriptString); + } + /// Runs the given JavaScript in the context of the current page. /// If you are looking for the result, use [runJavascriptReturningResult] instead. /// The Future completes with an error if a JavaScript error occurred. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart index 2451f2670030..17e896c94888 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/integration_test/webview_flutter_test.dart @@ -73,6 +73,27 @@ void main() { expect(currentUrl, secondaryUrl); }, skip: _skipDueToIssue86757); + testWidgets('evaluateJavascript', (WidgetTester tester) async { + final Completer controllerCompleter = + Completer(); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: WebView( + key: GlobalKey(), + initialUrl: primaryUrl, + onWebViewCreated: (WebViewController controller) { + controllerCompleter.complete(controller); + }, + javascriptMode: JavascriptMode.unrestricted, + ), + ), + ); + final WebViewController controller = await controllerCompleter.future; + final String result = await controller.evaluateJavascript('1 + 1'); + expect(result, equals('2')); + }); + testWidgets('loadUrl with headers', (WidgetTester tester) async { final Completer controllerCompleter = Completer(); diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart index 2da345171237..8460d457f6db 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart @@ -410,6 +410,16 @@ class WebViewController { _javascriptChannelRegistry.updateJavascriptChannelsFromSet(newChannels); } + @visibleForTesting + // ignore: public_member_api_docs + Future evaluateJavascript(String javascriptString) { + if (_settings.javascriptMode == JavascriptMode.disabled) { + return Future.error(FlutterError( + 'JavaScript mode must be enabled/unrestricted when calling evaluateJavascript.')); + } + return _webViewPlatformController.evaluateJavascript(javascriptString); + } + /// Runs the given JavaScript in the context of the current page. /// If you are looking for the result, use [runJavascriptReturningResult] instead. /// The Future completes with an error if a JavaScript error occurred. From e2f47104d25534e49b3d5b8a4c744d9debc3db5d Mon Sep 17 00:00:00 2001 From: "Bodhi Mulders (BeMacized)" Date: Thu, 28 Oct 2021 17:16:54 +0200 Subject: [PATCH 36/36] Fix merge conflicts --- packages/webview_flutter/webview_flutter_android/pubspec.yaml | 2 +- packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 577d37359af1..ac208a09ebc0 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 2.1.0 +version: 2.2.0 environment: sdk: ">=2.14.0 <3.0.0" diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index bfa4b8050e90..5176adb9749c 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/plugins/tree/master/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 2.1.0 +version: 2.2.0 environment: sdk: ">=2.14.0 <3.0.0"