[webview_flutter] Workaround old Android tablets select drop down crash (#2663)
diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md
index e24c832..efff00e 100644
--- a/packages/webview_flutter/CHANGELOG.md
+++ b/packages/webview_flutter/CHANGELOG.md
@@ -1,6 +1,7 @@
## 0.3.20+1
* OCMock module import -> #import, unit tests compile generated as library.
+* Fix select drop down crash on old Android tablets (https://github.com/flutter/flutter/issues/54164).
## 0.3.20
diff --git a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
index 477eefc..0aa2f58 100644
--- a/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
+++ b/packages/webview_flutter/android/src/main/java/io/flutter/plugins/webviewflutter/InputAwareWebView.java
@@ -7,10 +7,13 @@
import static android.content.Context.INPUT_METHOD_SERVICE;
import android.content.Context;
+import android.graphics.Rect;
+import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.webkit.WebView;
+import android.widget.ListPopupWindow;
/**
* A WebView subclass that mirrors the same implementation hacks that the system WebView does in
@@ -186,4 +189,45 @@
}
});
}
+
+ @Override
+ protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+ // This works around a crash when old (<67.0.3367.0) Chromium versions are used.
+
+ // Prior to Chromium 67.0.3367 the following sequence happens when a select drop down is shown
+ // on tablets:
+ //
+ // - WebView is calling ListPopupWindow#show
+ // - buildDropDown is invoked, which sets mDropDownList to a DropDownListView.
+ // - showAsDropDown is invoked - resulting in mDropDownList being added to the window and is
+ // also synchronously performing the following sequence:
+ // - WebView's focus change listener is loosing focus (as mDropDownList got it)
+ // - WebView is hiding all popups (as it lost focus)
+ // - WebView's SelectPopupDropDown#hide is invoked.
+ // - DropDownPopupWindow#dismiss is invoked setting mDropDownList to null.
+ // - mDropDownList#setSelection is invoked and is throwing a NullPointerException (as we just set mDropDownList to null).
+ //
+ // To workaround this, we drop the problematic focus lost call.
+ // See more details on: https://github.com/flutter/flutter/issues/54164
+ //
+ // We don't do this after Android P as it shipped with a new enough WebView version, and it's
+ // better to not do this on all future Android versions in case DropDownListView's code changes.
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P
+ && isCalledFromListPopupWindowShow()
+ && !focused) {
+ return;
+ }
+ super.onFocusChanged(focused, direction, previouslyFocusedRect);
+ }
+
+ private boolean isCalledFromListPopupWindowShow() {
+ StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+ for (int i = 0; i < stackTraceElements.length; i++) {
+ if (stackTraceElements[i].getClassName().equals(ListPopupWindow.class.getCanonicalName())
+ && stackTraceElements[i].getMethodName().equals("show")) {
+ return true;
+ }
+ }
+ return false;
+ }
}