Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 0c23f8f

Browse files
authored
[webview_flutter] Update webview packages for Android and iOS to implement runJavascript and runJavascriptReturningResult. (#4402)
* [webview_flutter_platform_interface] Update webview platform interface with new methods for running JavaScript * Fix tests * [webview_flutter] Implemented `runJavaScript` and `runJavaScriptForResult` in iOS and Android packages. * Remove accidental development team inclusion from project.pbxproj * Implemented PR feedback * Updated runJavaScriptForResult behaviour * Implemented PR feedback partially * Implement PR feedback * Update changelog * Implement PR feedback from interface PR * Update changelog * Revert inclusion of development team * Implement PR feedback * Implemented platform interface PR feedback * Update pubspec dependency * Fixed capitalisation * Fixed capitalisation * Fix warning * Partially implement PR feedback * Partially implement PR feedback * Format * Update podfile * Update podfile * Update podfiles * Update iOS project files * Update podspec * Remove unnecessary podfile configuration * Implemented PR feedback * Format * Revert podfile changes * Implemented PR feedback * Fix formatting * Fix formatting * Fixed test. * Re-add integration tests for deprecated evaluateJavascript method. * Fix merge conflicts
1 parent 29f46b4 commit 0c23f8f

File tree

19 files changed

+690
-218
lines changed

19 files changed

+690
-218
lines changed

packages/webview_flutter/webview_flutter/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 51 additions & 46 deletions
Large diffs are not rendered by default.

packages/webview_flutter/webview_flutter_android/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.2.0
2+
3+
* Implemented new `runJavascript` and `runJavascriptReturningResult` methods in platform interface.
4+
15
## 2.1.0
26

37
* Add `zoomEnabled` functionality.

packages/webview_flutter/webview_flutter_android/android/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,8 @@ android {
5858
}
5959
}
6060
}
61+
compileOptions {
62+
sourceCompatibility JavaVersion.VERSION_1_8
63+
targetCompatibility JavaVersion.VERSION_1_8
64+
}
6165
}

packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/FlutterWebView.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ public void onMethodCall(MethodCall methodCall, Result result) {
245245
currentUrl(result);
246246
break;
247247
case "evaluateJavascript":
248-
evaluateJavaScript(methodCall, result);
248+
case "runJavascriptReturningResult":
249+
evaluateJavaScript(methodCall, result, true);
250+
break;
251+
case "runJavascript":
252+
evaluateJavaScript(methodCall, result, false);
249253
break;
250254
case "addJavascriptChannels":
251255
addJavaScriptChannels(methodCall, result);
@@ -326,7 +330,8 @@ private void updateSettings(MethodCall methodCall, Result result) {
326330
}
327331

328332
@TargetApi(Build.VERSION_CODES.KITKAT)
329-
private void evaluateJavaScript(MethodCall methodCall, final Result result) {
333+
private void evaluateJavaScript(
334+
MethodCall methodCall, final Result result, final boolean returnValue) {
330335
String jsString = (String) methodCall.arguments;
331336
if (jsString == null) {
332337
throw new UnsupportedOperationException("JavaScript string cannot be null");
@@ -336,7 +341,11 @@ private void evaluateJavaScript(MethodCall methodCall, final Result result) {
336341
new android.webkit.ValueCallback<String>() {
337342
@Override
338343
public void onReceiveValue(String value) {
339-
result.success(value);
344+
if (returnValue) {
345+
result.success(value);
346+
} else {
347+
result.success(null);
348+
}
340349
}
341350
});
342351
}

packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/FlutterWebViewTest.java

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,46 @@
66

77
import static org.mockito.ArgumentMatchers.any;
88
import static org.mockito.ArgumentMatchers.anyBoolean;
9+
import static org.mockito.ArgumentMatchers.eq;
10+
import static org.mockito.ArgumentMatchers.isNull;
11+
import static org.mockito.Mockito.doAnswer;
912
import static org.mockito.Mockito.mock;
13+
import static org.mockito.Mockito.mockStatic;
1014
import static org.mockito.Mockito.times;
1115
import static org.mockito.Mockito.verify;
1216
import static org.mockito.Mockito.when;
1317

18+
import android.content.Context;
1419
import android.webkit.DownloadListener;
1520
import android.webkit.WebChromeClient;
1621
import android.webkit.WebView;
22+
import io.flutter.plugin.common.MethodCall;
23+
import io.flutter.plugin.common.MethodChannel;
1724
import java.util.HashMap;
1825
import java.util.Map;
1926
import org.junit.Before;
2027
import org.junit.Test;
28+
import org.mockito.MockedStatic;
2129

2230
public class FlutterWebViewTest {
2331
private WebChromeClient mockWebChromeClient;
2432
private DownloadListener mockDownloadListener;
2533
private WebViewBuilder mockWebViewBuilder;
2634
private WebView mockWebView;
35+
private MethodChannel.Result mockResult;
36+
private Context mockContext;
37+
private MethodChannel mockMethodChannel;
2738

2839
@Before
2940
public void before() {
41+
3042
mockWebChromeClient = mock(WebChromeClient.class);
3143
mockWebViewBuilder = mock(WebViewBuilder.class);
3244
mockWebView = mock(WebView.class);
3345
mockDownloadListener = mock(DownloadListener.class);
46+
mockResult = mock(MethodChannel.Result.class);
47+
mockContext = mock(Context.class);
48+
mockMethodChannel = mock(MethodChannel.class);
3449

3550
when(mockWebViewBuilder.setDomStorageEnabled(anyBoolean())).thenReturn(mockWebViewBuilder);
3651
when(mockWebViewBuilder.setJavaScriptCanOpenWindowsAutomatically(anyBoolean()))
@@ -42,12 +57,11 @@ public void before() {
4257
.thenReturn(mockWebViewBuilder);
4358
when(mockWebViewBuilder.setDownloadListener(any(DownloadListener.class)))
4459
.thenReturn(mockWebViewBuilder);
45-
4660
when(mockWebViewBuilder.build()).thenReturn(mockWebView);
4761
}
4862

4963
@Test
50-
public void createWebView_should_create_webview_with_default_configuration() {
64+
public void createWebView_shouldCreateWebViewWithDefaultConfiguration() {
5165
FlutterWebView.createWebView(
5266
mockWebViewBuilder, createParameterMap(false), mockWebChromeClient, mockDownloadListener);
5367

@@ -59,6 +73,97 @@ public void createWebView_should_create_webview_with_default_configuration() {
5973
verify(mockWebViewBuilder, times(1)).setZoomControlsEnabled(true);
6074
}
6175

76+
@Test(expected = UnsupportedOperationException.class)
77+
public void evaluateJavaScript_shouldThrowForNullString() {
78+
try (MockedStatic<FlutterWebView> mockedFlutterWebView = mockStatic(FlutterWebView.class)) {
79+
// Setup
80+
mockedFlutterWebView
81+
.when(
82+
new MockedStatic.Verification() {
83+
@Override
84+
public void apply() throws Throwable {
85+
FlutterWebView.createWebView(
86+
(WebViewBuilder) any(),
87+
(Map<String, Object>) any(),
88+
(WebChromeClient) any(),
89+
(DownloadListener) any());
90+
}
91+
})
92+
.thenReturn(mockWebView);
93+
FlutterWebView flutterWebView =
94+
new FlutterWebView(mockContext, mockMethodChannel, new HashMap<String, Object>(), null);
95+
96+
// Run
97+
flutterWebView.onMethodCall(new MethodCall("runJavascript", null), mockResult);
98+
}
99+
}
100+
101+
@Test
102+
public void evaluateJavaScript_shouldReturnValueOnSuccessForReturnValue() {
103+
try (MockedStatic<FlutterWebView> mockedFlutterWebView = mockStatic(FlutterWebView.class)) {
104+
// Setup
105+
mockedFlutterWebView
106+
.when(
107+
() ->
108+
FlutterWebView.createWebView(
109+
(WebViewBuilder) any(),
110+
(Map<String, Object>) any(),
111+
(WebChromeClient) any(),
112+
(DownloadListener) any()))
113+
.thenReturn(mockWebView);
114+
doAnswer(
115+
invocation -> {
116+
android.webkit.ValueCallback<String> callback = invocation.getArgument(1);
117+
callback.onReceiveValue("Test JavaScript Result");
118+
return null;
119+
})
120+
.when(mockWebView)
121+
.evaluateJavascript(eq("Test JavaScript String"), any());
122+
FlutterWebView flutterWebView =
123+
new FlutterWebView(mockContext, mockMethodChannel, new HashMap<String, Object>(), null);
124+
125+
// Run
126+
flutterWebView.onMethodCall(
127+
new MethodCall("runJavascriptReturningResult", "Test JavaScript String"), mockResult);
128+
129+
// Verify
130+
verify(mockResult, times(1)).success("Test JavaScript Result");
131+
}
132+
}
133+
134+
@Test
135+
public void evaluateJavaScript_shouldReturnNilOnSuccessForNoReturnValue() {
136+
try (MockedStatic<FlutterWebView> mockedFlutterWebView = mockStatic(FlutterWebView.class)) {
137+
// Setup
138+
mockedFlutterWebView
139+
.when(
140+
() ->
141+
FlutterWebView.createWebView(
142+
(WebViewBuilder) any(),
143+
(Map<String, Object>) any(),
144+
(WebChromeClient) any(),
145+
(DownloadListener) any()))
146+
.thenReturn(mockWebView);
147+
doAnswer(
148+
invocation -> {
149+
android.webkit.ValueCallback<String> callback = invocation.getArgument(1);
150+
callback.onReceiveValue("Test JavaScript Result");
151+
return null;
152+
})
153+
.when(mockWebView)
154+
.evaluateJavascript(eq("Test JavaScript String"), any());
155+
FlutterWebView flutterWebView =
156+
new FlutterWebView(mockContext, mockMethodChannel, new HashMap<String, Object>(), null);
157+
158+
// Run
159+
flutterWebView.onMethodCall(
160+
new MethodCall("runJavascript", "Test JavaScript String"), mockResult);
161+
162+
// Verify
163+
verify(mockResult, times(1)).success(isNull());
164+
}
165+
}
166+
62167
private Map<String, Object> createParameterMap(boolean usesHybridComposition) {
63168
Map<String, Object> params = new HashMap<>();
64169
params.put("usesHybridComposition", usesHybridComposition);

0 commit comments

Comments
 (0)