1717import android .webkit .WebView ;
1818import android .webkit .WebViewClient ;
1919import androidx .annotation .NonNull ;
20- import io . flutter . plugin . common . BinaryMessenger ;
20+ import androidx . annotation . VisibleForTesting ;
2121import io .flutter .plugin .common .MethodCall ;
2222import io .flutter .plugin .common .MethodChannel ;
2323import io .flutter .plugin .common .MethodChannel .MethodCallHandler ;
2828import java .util .Map ;
2929
3030public class FlutterWebView implements PlatformView , MethodCallHandler {
31+
3132 private static final String JS_CHANNEL_NAMES_FIELD = "javascriptChannelNames" ;
3233 private final WebView webView ;
3334 private final MethodChannel methodChannel ;
@@ -36,6 +37,7 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
3637
3738 // Verifies that a url opened by `Window.open` has a secure url.
3839 private class FlutterWebChromeClient extends WebChromeClient {
40+
3941 @ Override
4042 public boolean onCreateWindow (
4143 final WebView view , boolean isDialog , boolean isUserGesture , Message resultMsg ) {
@@ -83,8 +85,7 @@ public void onProgressChanged(WebView view, int progress) {
8385 @ SuppressWarnings ("unchecked" )
8486 FlutterWebView (
8587 final Context context ,
86- BinaryMessenger messenger ,
87- int id ,
88+ MethodChannel methodChannel ,
8889 Map <String , Object > params ,
8990 View containerView ) {
9091
@@ -93,37 +94,34 @@ public void onProgressChanged(WebView view, int progress) {
9394 (DisplayManager ) context .getSystemService (Context .DISPLAY_SERVICE );
9495 displayListenerProxy .onPreWebViewInitialization (displayManager );
9596
96- Boolean usesHybridComposition = (Boolean ) params .get ("usesHybridComposition" );
9797 webView =
98- (usesHybridComposition )
99- ? new WebView (context )
100- : new InputAwareWebView (context , containerView );
98+ createWebView (
99+ new WebViewBuilder (context , containerView ), params , new FlutterWebChromeClient ());
101100
102101 displayListenerProxy .onPostWebViewInitialization (displayManager );
103102
104103 platformThreadHandler = new Handler (context .getMainLooper ());
105- // Allow local storage.
106- webView .getSettings ().setDomStorageEnabled (true );
107- webView .getSettings ().setJavaScriptCanOpenWindowsAutomatically (true );
108-
109- // Multi windows is set with FlutterWebChromeClient by default to handle internal bug: b/159892679.
110- webView .getSettings ().setSupportMultipleWindows (true );
111- webView .setWebChromeClient (new FlutterWebChromeClient ());
112104
113- methodChannel = new MethodChannel ( messenger , "plugins.flutter.io/webview_" + id ) ;
114- methodChannel .setMethodCallHandler (this );
105+ this . methodChannel = methodChannel ;
106+ this . methodChannel .setMethodCallHandler (this );
115107
116108 flutterWebViewClient = new FlutterWebViewClient (methodChannel );
117109 Map <String , Object > settings = (Map <String , Object >) params .get ("settings" );
118- if (settings != null ) applySettings (settings );
110+ if (settings != null ) {
111+ applySettings (settings );
112+ }
119113
120114 if (params .containsKey (JS_CHANNEL_NAMES_FIELD )) {
121115 List <String > names = (List <String >) params .get (JS_CHANNEL_NAMES_FIELD );
122- if (names != null ) registerJavaScriptChannelNames (names );
116+ if (names != null ) {
117+ registerJavaScriptChannelNames (names );
118+ }
123119 }
124120
125121 Integer autoMediaPlaybackPolicy = (Integer ) params .get ("autoMediaPlaybackPolicy" );
126- if (autoMediaPlaybackPolicy != null ) updateAutoMediaPlaybackPolicy (autoMediaPlaybackPolicy );
122+ if (autoMediaPlaybackPolicy != null ) {
123+ updateAutoMediaPlaybackPolicy (autoMediaPlaybackPolicy );
124+ }
127125 if (params .containsKey ("userAgent" )) {
128126 String userAgent = (String ) params .get ("userAgent" );
129127 updateUserAgent (userAgent );
@@ -134,6 +132,44 @@ public void onProgressChanged(WebView view, int progress) {
134132 }
135133 }
136134
135+ /**
136+ * Creates a {@link android.webkit.WebView} and configures it according to the supplied
137+ * parameters.
138+ *
139+ * <p>The {@link WebView} is configured with the following predefined settings:
140+ *
141+ * <ul>
142+ * <li>always enable the DOM storage API;
143+ * <li>always allow JavaScript to automatically open windows;
144+ * <li>always allow support for multiple windows;
145+ * <li>always use the {@link FlutterWebChromeClient} as web Chrome client.
146+ * </ul>
147+ *
148+ * <p><strong>Important:</strong> This method is visible for testing purposes only and should
149+ * never be called from outside this class.
150+ *
151+ * @param webViewBuilder a {@link WebViewBuilder} which is responsible for building the {@link
152+ * WebView}.
153+ * @param params creation parameters received over the method channel.
154+ * @param webChromeClient an implementation of WebChromeClient This value may be null.
155+ * @return The new {@link android.webkit.WebView} object.
156+ */
157+ @ VisibleForTesting
158+ static WebView createWebView (
159+ WebViewBuilder webViewBuilder , Map <String , Object > params , WebChromeClient webChromeClient ) {
160+ boolean usesHybridComposition = Boolean .TRUE .equals (params .get ("usesHybridComposition" ));
161+ webViewBuilder
162+ .setUsesHybridComposition (usesHybridComposition )
163+ .setDomStorageEnabled (true ) // Always enable DOM storage API.
164+ .setJavaScriptCanOpenWindowsAutomatically (
165+ true ) // Always allow automatically opening of windows.
166+ .setSupportMultipleWindows (true ) // Always support multiple windows.
167+ .setWebChromeClient (
168+ webChromeClient ); // Always use {@link FlutterWebChromeClient} as web Chrome client.
169+
170+ return webViewBuilder .build ();
171+ }
172+
137173 @ Override
138174 public View getView () {
139175 return webView ;
@@ -369,7 +405,9 @@ private void applySettings(Map<String, Object> settings) {
369405 switch (key ) {
370406 case "jsMode" :
371407 Integer mode = (Integer ) settings .get (key );
372- if (mode != null ) updateJsMode (mode );
408+ if (mode != null ) {
409+ updateJsMode (mode );
410+ }
373411 break ;
374412 case "hasNavigationDelegate" :
375413 final boolean hasNavigationDelegate = (boolean ) settings .get (key );
0 commit comments