Commit 310a7020 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Android] Pass fully initialized view to accessory adapter or exit

As described in the linked bug, the adapter assumed WindowAndroid to
never be null which causes a crash.
With this CL, the view will be initialized early on and if WindowAndroid
is nullptr, the creation of the view (and the adapter) will be aborted.

To do that, the unused constructor parameters for label width and length
were removed.

Bug: 1048849, 1049090
Change-Id: I60151a560907a984ba4e45ee949624400b8f86da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2037672
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738564}
parent 5b1e0dfc
...@@ -79,15 +79,9 @@ public class AutofillKeyboardAccessoryViewBridge ...@@ -79,15 +79,9 @@ public class AutofillKeyboardAccessoryViewBridge
* This function should be called at most one time. * This function should be called at most one time.
* @param nativeAutofillKeyboardAccessory Handle to the native counterpart. * @param nativeAutofillKeyboardAccessory Handle to the native counterpart.
* @param windowAndroid The window on which to show the suggestions. * @param windowAndroid The window on which to show the suggestions.
* @param animationDurationMillis If 0, do not animate. Otherwise, animation duration in each
* direction. We reverse animation to scroll the first suggestion
* (which is a hint to call attention to the accessory) out of
* the viewport at the end of the reversed animation.
* @param shouldLimitLabelWidth If true, limit suggestion label width to 1/2 device's width.
*/ */
@CalledByNative @CalledByNative
private void init(long nativeAutofillKeyboardAccessory, WindowAndroid windowAndroid, private void init(long nativeAutofillKeyboardAccessory, WindowAndroid windowAndroid) {
int animationDurationMillis, boolean shouldLimitLabelWidth) {
mContext = windowAndroid.getActivity().get(); mContext = windowAndroid.getActivity().get();
assert mContext != null; assert mContext != null;
if (mContext instanceof ChromeActivity) { if (mContext instanceof ChromeActivity) {
......
...@@ -35,12 +35,8 @@ base::string16 CreateLabel(const Suggestion& suggestion) { ...@@ -35,12 +35,8 @@ base::string16 CreateLabel(const Suggestion& suggestion) {
} // namespace } // namespace
AutofillKeyboardAccessoryAdapter::AutofillKeyboardAccessoryAdapter( AutofillKeyboardAccessoryAdapter::AutofillKeyboardAccessoryAdapter(
base::WeakPtr<AutofillPopupController> controller, base::WeakPtr<AutofillPopupController> controller)
unsigned int animation_duration_millis, : controller_(controller) {}
bool should_limit_label_width)
: controller_(controller),
animation_duration_millis_(animation_duration_millis),
should_limit_label_width_(should_limit_label_width) {}
AutofillKeyboardAccessoryAdapter::~AutofillKeyboardAccessoryAdapter() = default; AutofillKeyboardAccessoryAdapter::~AutofillKeyboardAccessoryAdapter() = default;
...@@ -48,7 +44,6 @@ AutofillKeyboardAccessoryAdapter::~AutofillKeyboardAccessoryAdapter() = default; ...@@ -48,7 +44,6 @@ AutofillKeyboardAccessoryAdapter::~AutofillKeyboardAccessoryAdapter() = default;
void AutofillKeyboardAccessoryAdapter::Show() { void AutofillKeyboardAccessoryAdapter::Show() {
DCHECK(view_) << "Show called before a View was set!"; DCHECK(view_) << "Show called before a View was set!";
view_->Initialize(animation_duration_millis_, should_limit_label_width_);
OnSuggestionsChanged(); OnSuggestionsChanged();
} }
......
...@@ -26,9 +26,7 @@ class AutofillKeyboardAccessoryAdapter : public AutofillPopupView, ...@@ -26,9 +26,7 @@ class AutofillKeyboardAccessoryAdapter : public AutofillPopupView,
public AutofillPopupController { public AutofillPopupController {
public: public:
AutofillKeyboardAccessoryAdapter( AutofillKeyboardAccessoryAdapter(
base::WeakPtr<AutofillPopupController> controller, base::WeakPtr<AutofillPopupController> controller);
unsigned int animation_duration_millis,
bool should_limit_label_width);
~AutofillKeyboardAccessoryAdapter() override; ~AutofillKeyboardAccessoryAdapter() override;
// Interface describing the minimal capabilities for the native view. // Interface describing the minimal capabilities for the native view.
...@@ -36,9 +34,9 @@ class AutofillKeyboardAccessoryAdapter : public AutofillPopupView, ...@@ -36,9 +34,9 @@ class AutofillKeyboardAccessoryAdapter : public AutofillPopupView,
public: public:
virtual ~AccessoryView() = default; virtual ~AccessoryView() = default;
// Initializes the Java-side of this bridge. // Initializes the Java-side of this bridge. Returns true after a successful
virtual void Initialize(unsigned int animation_duration_millis, // creation and false otherwise.
bool should_limit_label_width) = 0; virtual bool Initialize() = 0;
// Requests to dismiss this view. // Requests to dismiss this view.
virtual void Hide() = 0; virtual void Hide() = 0;
...@@ -106,12 +104,6 @@ class AutofillKeyboardAccessoryAdapter : public AutofillPopupView, ...@@ -106,12 +104,6 @@ class AutofillKeyboardAccessoryAdapter : public AutofillPopupView,
// The labels to be used for the input chips. // The labels to be used for the input chips.
std::vector<base::string16> labels_; std::vector<base::string16> labels_;
// If 0, don't animate suggestion view.
const unsigned int animation_duration_millis_;
// If true, limits label width to 1/2 device's width.
const bool should_limit_label_width_;
// Position that the front element has in the suggestion list returned by // Position that the front element has in the suggestion list returned by
// controller_. It is used to determine the offset suggestions. // controller_. It is used to determine the offset suggestions.
base::Optional<int> front_element_; base::Optional<int> front_element_;
......
...@@ -37,7 +37,7 @@ class MockAccessoryView ...@@ -37,7 +37,7 @@ class MockAccessoryView
: public AutofillKeyboardAccessoryAdapter::AccessoryView { : public AutofillKeyboardAccessoryAdapter::AccessoryView {
public: public:
MockAccessoryView() {} MockAccessoryView() {}
MOCK_METHOD2(Initialize, void(unsigned int, bool)); MOCK_METHOD0(Initialize, bool());
MOCK_METHOD0(Hide, void()); MOCK_METHOD0(Hide, void());
MOCK_METHOD0(Show, void()); MOCK_METHOD0(Show, void());
MOCK_METHOD3(ConfirmDeletion, MOCK_METHOD3(ConfirmDeletion,
...@@ -116,7 +116,7 @@ class AutofillKeyboardAccessoryAdapterTest : public testing::Test { ...@@ -116,7 +116,7 @@ class AutofillKeyboardAccessoryAdapterTest : public testing::Test {
autofill_accessory_adapter_ = autofill_accessory_adapter_ =
std::make_unique<AutofillKeyboardAccessoryAdapter>( std::make_unique<AutofillKeyboardAccessoryAdapter>(
popup_controller_->GetWeakPtr(), 0, false); popup_controller_->GetWeakPtr());
autofill_accessory_adapter_->SetAccessoryView(std::move(view)); autofill_accessory_adapter_->SetAccessoryView(std::move(view));
} }
...@@ -151,11 +151,7 @@ class AutofillKeyboardAccessoryAdapterTest : public testing::Test { ...@@ -151,11 +151,7 @@ class AutofillKeyboardAccessoryAdapterTest : public testing::Test {
}; };
TEST_F(AutofillKeyboardAccessoryAdapterTest, ShowingInitializesAndUpdatesView) { TEST_F(AutofillKeyboardAccessoryAdapterTest, ShowingInitializesAndUpdatesView) {
{ EXPECT_CALL(*view(), Show());
::testing::Sequence s;
EXPECT_CALL(*view(), Initialize(_, _));
EXPECT_CALL(*view(), Show());
}
adapter_as_view()->Show(); adapter_as_view()->Show();
} }
......
...@@ -38,16 +38,17 @@ AutofillKeyboardAccessoryView::~AutofillKeyboardAccessoryView() { ...@@ -38,16 +38,17 @@ AutofillKeyboardAccessoryView::~AutofillKeyboardAccessoryView() {
base::android::AttachCurrentThread(), java_object_); base::android::AttachCurrentThread(), java_object_);
} }
void AutofillKeyboardAccessoryView::Initialize( bool AutofillKeyboardAccessoryView::Initialize() {
unsigned int animation_duration_millis,
bool should_limit_label_width) {
ui::ViewAndroid* view_android = controller_->container_view(); ui::ViewAndroid* view_android = controller_->container_view();
DCHECK(view_android); if (!view_android)
return false;
ui::WindowAndroid* window_android = view_android->GetWindowAndroid();
if (!window_android)
return false; // The window might not be attached (yet or anymore).
Java_AutofillKeyboardAccessoryViewBridge_init( Java_AutofillKeyboardAccessoryViewBridge_init(
base::android::AttachCurrentThread(), java_object_, base::android::AttachCurrentThread(), java_object_,
reinterpret_cast<intptr_t>(this), reinterpret_cast<intptr_t>(this), window_android->GetJavaObject());
view_android->GetWindowAndroid()->GetJavaObject(), return true;
animation_duration_millis, should_limit_label_width);
} }
void AutofillKeyboardAccessoryView::Hide() { void AutofillKeyboardAccessoryView::Hide() {
......
...@@ -30,8 +30,7 @@ class AutofillKeyboardAccessoryView ...@@ -30,8 +30,7 @@ class AutofillKeyboardAccessoryView
~AutofillKeyboardAccessoryView() override; ~AutofillKeyboardAccessoryView() override;
// Implementation of AutofillKeyboardAccessoryAdapter::AccessoryView. // Implementation of AutofillKeyboardAccessoryAdapter::AccessoryView.
void Initialize(unsigned int animation_duration_millis, bool Initialize() override;
bool limit_label_width) override;
void Hide() override; void Hide() override;
void Show() override; void Show() override;
void ConfirmDeletion(const base::string16& confirmation_title, void ConfirmDeletion(const base::string16& confirmation_title,
......
...@@ -159,7 +159,7 @@ void AutofillPopupViewAndroid::PopupDismissed( ...@@ -159,7 +159,7 @@ void AutofillPopupViewAndroid::PopupDismissed(
delete this; delete this;
} }
void AutofillPopupViewAndroid::Init() { bool AutofillPopupViewAndroid::Init() {
JNIEnv* env = base::android::AttachCurrentThread(); JNIEnv* env = base::android::AttachCurrentThread();
ui::ViewAndroid* view_android = controller_->container_view(); ui::ViewAndroid* view_android = controller_->container_view();
...@@ -167,11 +167,15 @@ void AutofillPopupViewAndroid::Init() { ...@@ -167,11 +167,15 @@ void AutofillPopupViewAndroid::Init() {
popup_view_ = view_android->AcquireAnchorView(); popup_view_ = view_android->AcquireAnchorView();
const ScopedJavaLocalRef<jobject> view = popup_view_.view(); const ScopedJavaLocalRef<jobject> view = popup_view_.view();
if (view.is_null()) if (view.is_null())
return; return false;
ui::WindowAndroid* window_android = view_android->GetWindowAndroid();
if (!window_android)
return false; // The window might not be attached (yet or anymore).
java_object_.Reset(Java_AutofillPopupBridge_create( java_object_.Reset(Java_AutofillPopupBridge_create(
env, view, reinterpret_cast<intptr_t>(this), env, view, reinterpret_cast<intptr_t>(this),
view_android->GetWindowAndroid()->GetJavaObject())); window_android->GetJavaObject()));
return true;
} }
bool AutofillPopupViewAndroid::WasSuppressed() { bool AutofillPopupViewAndroid::WasSuppressed() {
...@@ -184,18 +188,21 @@ bool AutofillPopupViewAndroid::WasSuppressed() { ...@@ -184,18 +188,21 @@ bool AutofillPopupViewAndroid::WasSuppressed() {
AutofillPopupView* AutofillPopupView::Create( AutofillPopupView* AutofillPopupView::Create(
base::WeakPtr<AutofillPopupController> controller) { base::WeakPtr<AutofillPopupController> controller) {
if (IsKeyboardAccessoryEnabled()) { if (IsKeyboardAccessoryEnabled()) {
auto adapter = std::make_unique<AutofillKeyboardAccessoryAdapter>( auto adapter =
controller, GetKeyboardAccessoryAnimationDuration(), std::make_unique<AutofillKeyboardAccessoryAdapter>(controller);
ShouldLimitKeyboardAccessorySuggestionLabelWidth()); auto accessory_view =
adapter->SetAccessoryView( std::make_unique<AutofillKeyboardAccessoryView>(adapter.get());
std::make_unique<AutofillKeyboardAccessoryView>(adapter.get())); if (!accessory_view->Initialize())
return nullptr; // Don't create an adapter without initialized view.
adapter->SetAccessoryView(std::move(accessory_view));
return adapter.release(); return adapter.release();
} }
auto popup_view = auto popup_view =
std::make_unique<AutofillPopupViewAndroid>(controller.get()); std::make_unique<AutofillPopupViewAndroid>(controller.get());
popup_view->Init(); if (!popup_view->Init() || popup_view->WasSuppressed())
return popup_view->WasSuppressed() ? nullptr : popup_view.release(); return nullptr;
return popup_view.release();
} }
} // namespace autofill } // namespace autofill
...@@ -53,7 +53,7 @@ class AutofillPopupViewAndroid : public AutofillPopupView { ...@@ -53,7 +53,7 @@ class AutofillPopupViewAndroid : public AutofillPopupView {
private: private:
friend class AutofillPopupView; friend class AutofillPopupView;
// Creates the AutofillPopupBridge Java object. // Creates the AutofillPopupBridge Java object.
void Init(); bool Init();
// Returns whether the dropdown was suppressed (mainly due to not enough // Returns whether the dropdown was suppressed (mainly due to not enough
// screen space available). // screen space available).
bool WasSuppressed(); bool WasSuppressed();
......
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