Android: Ensure |OnDetachedFromWindow| is invoked upon destruction
https://crrev.com/c/1020942 meant to make sure |DetachedFromWindow| is
invoked upon ViewAndroid destruction. This had a bug when
WindowAndroid is destroyed first, which can happen for Chromecast
where WebContents destruction is delayed by design.
WindowAndroid dtor invokes |GetWindowAndroid| indirectly via its
base dtor (through RemoveAllChildren), but it didn't work as intended
because |GetWindowAndroid| is a virtual function. So it ended up
calling |ViewAndroid::GetWindowAndroid|, not
|WindowAndroid::GetWindowAndroid|.
This CL fixes it by pulling out the task of invoking
|OnDetachedFromWindow| so that the destructor won't use the virtual
function. WindowAndroid can call |OnDetachedFromWindow| in its dtor
since it doesn't need |GetWindowAndroid| - it knows for sure
WindowAndroid (itself) is present.
Bug: b/78251221
Change-Id: I754e45ca3ea61ceb86101ede3b529e75e206689f
Reviewed-on: https://chromium-review.googlesource.com/1102823
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: Bo <boliu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568064}
diff --git a/ui/android/view_android.cc b/ui/android/view_android.cc
index 7a17c28..ec031a8 100644
--- a/ui/android/view_android.cc
+++ b/ui/android/view_android.cc
@@ -88,7 +88,7 @@
ViewAndroid::ViewAndroid() : ViewAndroid(LayoutType::NORMAL) {}
ViewAndroid::~ViewAndroid() {
- RemoveAllChildren();
+ RemoveAllChildren(GetWindowAndroid() != nullptr);
observer_list_.Clear();
RemoveFromParent();
}
@@ -252,11 +252,10 @@
return gfx::PointF(x + loc_x, y + loc_y);
}
-void ViewAndroid::RemoveAllChildren() {
- bool has_window = GetWindowAndroid();
+void ViewAndroid::RemoveAllChildren(bool attached_to_window) {
auto it = children_.begin();
while (it != children_.end()) {
- if (has_window)
+ if (attached_to_window)
(*it)->OnDetachedFromWindow();
(*it)->parent_ = nullptr;
// erase returns a new iterator for the element following the ereased one.
diff --git a/ui/android/view_android.h b/ui/android/view_android.h
index c723346..5d2d2a2 100644
--- a/ui/android/view_android.h
+++ b/ui/android/view_android.h
@@ -179,6 +179,8 @@
ViewAndroid* parent() const { return parent_; }
protected:
+ void RemoveAllChildren(bool attached_to_window);
+
ViewAndroid* parent_;
private:
@@ -204,7 +206,6 @@
bool ScrollTo(float x, float y);
void RemoveChild(ViewAndroid* child);
- void RemoveAllChildren();
void OnAttachedToWindow();
void OnDetachedFromWindow();
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc
index 9b28a66e..f099ea08 100644
--- a/ui/android/window_android.cc
+++ b/ui/android/window_android.cc
@@ -152,6 +152,7 @@
WindowAndroid::~WindowAndroid() {
DCHECK(parent_ == nullptr) << "WindowAndroid must be a root view.";
DCHECK(!compositor_);
+ RemoveAllChildren(true);
Java_WindowAndroid_clearNativePointer(AttachCurrentThread(), GetJavaObject());
}