Commit e4d32f59 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Android][Crash] Ensure accessory passes valid content view to UiUtils

Currently, the keyboard accessory uses the focused view in the activity
as view to check for keyboard visibility. This works most of the time,
when an input field is focused but it's thinkable that the focus moves
away (most likely programmatically) which could lead to the observed
crashes.

This CL now ensures, that the focused view is exclusively used when a
keyboard needs to be shown and the detection (which relies on the
content area layout) is always invoked with the content view.

Bug: 876231
Change-Id: Ib65c7985987291cd2b85098b920106dbde40753d
Reviewed-on: https://chromium-review.googlesource.com/1183423Reviewed-by: default avatarTheresa <twellington@chromium.org>
Commit-Queue: Friedrich Horschig [CEST] <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584813}
parent 43ac8e14
...@@ -218,7 +218,7 @@ class ManualFillingMediator ...@@ -218,7 +218,7 @@ class ManualFillingMediator
void dismiss() { void dismiss() {
mKeyboardAccessory.dismiss(); mKeyboardAccessory.dismiss();
UiUtils.hideKeyboard(mActivity.getCurrentFocus()); if (getContentView() != null) UiUtils.hideKeyboard(getContentView());
} }
void notifyPopupOpened(DropdownPopupWindow popup) { void notifyPopupOpened(DropdownPopupWindow popup) {
...@@ -239,17 +239,16 @@ class ManualFillingMediator ...@@ -239,17 +239,16 @@ class ManualFillingMediator
mAccessorySheet.setActiveTab(tabIndex); mAccessorySheet.setActiveTab(tabIndex);
if (mPopup != null && mPopup.isShowing()) mPopup.dismiss(); if (mPopup != null && mPopup.isShowing()) mPopup.dismiss();
// If there is a keyboard, update the accessory sheet's height and hide the keyboard. // If there is a keyboard, update the accessory sheet's height and hide the keyboard.
View focusedView = mActivity.getCurrentFocus(); if (getContentView() != null && getContentView().getRootView() != null) {
if (focusedView != null) { mAccessorySheet.setHeight(
mAccessorySheet.setHeight(calculateAccessorySheetHeight(focusedView.getRootView())); calculateAccessorySheetHeight(getContentView().getRootView()));
UiUtils.hideKeyboard(focusedView); UiUtils.hideKeyboard(getContentView());
} }
} }
@Override @Override
public void onCloseAccessorySheet() { public void onCloseAccessorySheet() {
View focusedView = mActivity.getCurrentFocus(); if (getContentView() == null || UiUtils.isKeyboardShowing(mActivity, getContentView())) {
if (focusedView == null || UiUtils.isKeyboardShowing(mActivity, focusedView)) {
return; // If the keyboard is showing or is starting to show, the sheet closes gently. return; // If the keyboard is showing or is starting to show, the sheet closes gently.
} }
mActivity.getFullscreenManager().setBottomControlsHeight(mPreviousControlHeight); mActivity.getFullscreenManager().setBottomControlsHeight(mPreviousControlHeight);
...@@ -262,7 +261,7 @@ class ManualFillingMediator ...@@ -262,7 +261,7 @@ class ManualFillingMediator
public void onOpenKeyboard() { public void onOpenKeyboard() {
assert mActivity != null : "ManualFillingMediator needs initialization."; assert mActivity != null : "ManualFillingMediator needs initialization.";
mActivity.getFullscreenManager().setBottomControlsHeight(calculateAccessoryBarHeight()); mActivity.getFullscreenManager().setBottomControlsHeight(calculateAccessoryBarHeight());
UiUtils.showKeyboard(mActivity.getCurrentFocus()); if (mActivity.getCurrentFocus() != null) UiUtils.showKeyboard(mActivity.getCurrentFocus());
} }
@Override @Override
...@@ -275,6 +274,20 @@ class ManualFillingMediator ...@@ -275,6 +274,20 @@ class ManualFillingMediator
mActivity.getFullscreenManager().setBottomControlsHeight(newControlsHeight); mActivity.getFullscreenManager().setBottomControlsHeight(newControlsHeight);
} }
/**
* When trying to get the content of the active tab, there are several cases where a component
* can be null - usually use before initialization or after destruction.
* This helper ensures that the IDE warns about unchecked use of the all Nullable methods and
* provides a shorthand for checking that all components are ready to use.
* @return The content {@link View} of the held {@link ChromeActivity} or null if any part of it
* isn't ready to use.
*/
private @Nullable View getContentView() {
if (mActivity == null) return null;
if (mActivity.getActivityTab() == null) return null;
return mActivity.getActivityTab().getContentView();
}
private AccessoryState getOrCreateAccessoryState(Tab tab) { private AccessoryState getOrCreateAccessoryState(Tab tab) {
assert tab != null : "Accessory state was requested without providing a non-null tab!"; assert tab != null : "Accessory state was requested without providing a non-null tab!";
AccessoryState state = mModel.get(tab); AccessoryState state = mModel.get(tab);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment