diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java --- a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java +++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopup.java @@ -97,8 +97,13 @@ public class SelectPopup } /** Close popup. Called when {@link WindowAndroid} is updated. */ public void close() { + // Dismiss the live AlertDialog/DropdownPopupWindow before dropping the + // reference, otherwise the orphaned dialog's listeners can later call + // selectMenuItems() against a re-bound popup_client_ (cross-popup + // misdelivery) or an unbound one (browser-process near-null crash). + if (mPopupView != null) mPopupView.hide(/*sendsCancelMessage=*/true); mPopupView = null; } diff --git a/content/browser/android/select_popup.cc b/content/browser/android/select_popup.cc --- a/content/browser/android/select_popup.cc +++ b/content/browser/android/select_popup.cc @@ -139,9 +139,14 @@ void SelectPopup::SelectMenuItems(JNIEnv* env, int64_t selectPopupDelegate, const JavaRef& indices) { blink::mojom::PopupMenuClient* popup_client_raw_ptr = reinterpret_cast(selectPopupDelegate); - DCHECK(popup_client_raw_ptr && popup_client_.get() == popup_client_raw_ptr); + // Defense-in-depth: refuse to dispatch if the Java-side delegate no longer + // matches the currently-bound client (orphaned dialog from a prior + // WindowAndroid swap) or if the remote was reset. + if (!popup_client_ || popup_client_.get() != popup_client_raw_ptr) { + return; + } if (indices.is_null()) { popup_client_->DidCancel(); return;