Commit cb43c01a authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: Fix a bug not receiving activity state update

The reported bug is a corner case where the WebContents at the front
when Chrome is put background, is not at the front when Chrome is back
to foreground. When coming to foreground in normal flow,
|OnAttachedToWindow| callback reestablishes the front WebContents'
ActivityStateObserver(ViewEventSinkImpl) first, which then reacts to
|onActivityResumed| callback to update the state to 'resumed' as
expected. The bug happens because the WebContents, not being in the
front anymore, loses the chance to receive |onActivityResumed| when
Chrome gets foreground, since it is still in the state where the
observer is not registered. The observer is added later when the tab
is moved to the front, upon receiving |onAttachedToWindow|
callback. The observer will still remain in paused state that causes
inconsistency leading the the bug.

This CL fixes the bug by checking activity state when registring the
activity state observer, which is done when attached to window. If it
is already in the 'resumed' state, it invokes |onActivityResumed| to
put WebContents in the right state. In a normal flow this will make
|onActivityResumed| invoked twice but it is ok - the second one will
be no-op.

Bug: 852336
Change-Id: I24aae020908b6a537b258c44b26e63fe5b314474
Reviewed-on: https://chromium-review.googlesource.com/1105344
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568670}
parent 10752e4f
...@@ -6,6 +6,7 @@ package org.chromium.content.browser; ...@@ -6,6 +6,7 @@ package org.chromium.content.browser;
import android.content.res.Configuration; import android.content.res.Configuration;
import org.chromium.base.ActivityState;
import org.chromium.base.ObserverList; import org.chromium.base.ObserverList;
import org.chromium.content.browser.webcontents.WebContentsImpl; import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
...@@ -130,6 +131,12 @@ public final class WindowEventObserverManager implements DisplayAndroidObserver ...@@ -130,6 +131,12 @@ public final class WindowEventObserverManager implements DisplayAndroidObserver
private void addActivityStateObserver() { private void addActivityStateObserver() {
if (!mAttachedToWindow || mWindowAndroid == null) return; if (!mAttachedToWindow || mWindowAndroid == null) return;
mWindowAndroid.addActivityStateObserver(mViewEventSink); mWindowAndroid.addActivityStateObserver(mViewEventSink);
// Sets the state of ViewEventSink right if activity is already in resumed state.
// Can happen when the front tab gets moved down in the stack while Chrome
// is in background. See https://crbug.com/852336.
if (mWindowAndroid.getActivityState() == ActivityState.RESUMED) {
mViewEventSink.onActivityResumed();
}
} }
private void addUiObservers() { private void addUiObservers() {
......
...@@ -33,6 +33,8 @@ public class ActivityWindowAndroid ...@@ -33,6 +33,8 @@ public class ActivityWindowAndroid
private int mNextRequestCode; private int mNextRequestCode;
private boolean mListenToActivityState;
/** /**
* Creates an Activity-specific WindowAndroid with associated intent functionality. * Creates an Activity-specific WindowAndroid with associated intent functionality.
* TODO(jdduke): Remove this overload when all callsites have been updated to * TODO(jdduke): Remove this overload when all callsites have been updated to
...@@ -54,6 +56,7 @@ public class ActivityWindowAndroid ...@@ -54,6 +56,7 @@ public class ActivityWindowAndroid
if (activity == null) { if (activity == null) {
throw new IllegalArgumentException("Context is not and does not wrap an Activity"); throw new IllegalArgumentException("Context is not and does not wrap an Activity");
} }
mListenToActivityState = listenToActivityState;
if (listenToActivityState) { if (listenToActivityState) {
ApplicationStatus.registerStateListenerForActivity(this, activity); ApplicationStatus.registerStateListenerForActivity(this, activity);
} }
...@@ -180,6 +183,13 @@ public class ActivityWindowAndroid ...@@ -180,6 +183,13 @@ public class ActivityWindowAndroid
} }
} }
@Override
@ActivityState
public int getActivityState() {
return mListenToActivityState ? ApplicationStatus.getStateForActivity(getActivity().get())
: super.getActivityState();
}
@Override @Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) { int oldTop, int oldRight, int oldBottom) {
......
...@@ -25,6 +25,7 @@ import android.view.View; ...@@ -25,6 +25,7 @@ import android.view.View;
import android.view.Window; import android.view.Window;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import org.chromium.base.ActivityState;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.Callback; import org.chromium.base.Callback;
import org.chromium.base.ContextUtils; import org.chromium.base.ContextUtils;
...@@ -582,6 +583,15 @@ public class WindowAndroid implements AndroidPermissionDelegate { ...@@ -582,6 +583,15 @@ public class WindowAndroid implements AndroidPermissionDelegate {
mActivityStateObservers.removeObserver(observer); mActivityStateObservers.removeObserver(observer);
} }
/**
* @return Current state of the associated {@link Activity}. Can be overriden
* to return the correct state. {@code ActivityState.DESTROYED} by default.
*/
@ActivityState
public int getActivityState() {
return ActivityState.DESTROYED;
}
@CalledByNative @CalledByNative
private void requestVSyncUpdate() { private void requestVSyncUpdate() {
if (mVSyncPaused) { if (mVSyncPaused) {
......
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