Commit db7cd728 authored by Lijin Shen's avatar Lijin Shen Committed by Commit Bot

[Messages] Dismiss all messages when tab changed

1. Add a listener for queue to be notified of tab changes
2. dismiss all messages when tab changes

Bug: 1123947
Change-Id: Ibd91c432a1dd93087127ce8c03e45d3af9f57ca1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2538675Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarPavel Yatsuk <pavely@chromium.org>
Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Commit-Queue: Lijin Shen <lazzzis@google.com>
Cr-Commit-Position: refs/heads/master@{#828777}
parent 1c39aec2
......@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.messages;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils;
......@@ -15,6 +16,8 @@ import org.chromium.chrome.browser.layouts.LayoutStateProvider;
import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver;
import org.chromium.chrome.browser.layouts.LayoutType;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.components.messages.ManagedMessageDispatcher;
import org.chromium.components.messages.MessageQueueDelegate;
import org.chromium.ui.util.TokenHolder;
......@@ -32,6 +35,7 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
private int mBrowserControlsToken = TokenHolder.INVALID_TOKEN;
private BrowserControlsObserver mBrowserControlsObserver;
private LayoutStateProvider mLayoutStateProvider;
private TabModelSelector mTabModelSelector;
private FullscreenManager.Observer mFullScreenObserver = new Observer() {
private int mToken = TokenHolder.INVALID_TOKEN;
......@@ -53,15 +57,25 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
@Override
public void onStartedShowing(int layoutType, boolean showToolbar) {
if (layoutType == LayoutType.TAB_SWITCHER) {
if (mToken == TokenHolder.INVALID_TOKEN && layoutType != LayoutType.BROWSING) {
mToken = suspendQueue();
}
}
@Override
public void onFinishedHiding(int layoutType) {
if (layoutType == LayoutType.TAB_SWITCHER) {
if (mToken != TokenHolder.INVALID_TOKEN && layoutType == LayoutType.BROWSING) {
resumeQueue(mToken);
mToken = TokenHolder.INVALID_TOKEN;
}
}
};
private TabModelObserver mTabModelObserver = new TabModelObserver() {
@Override
public void didSelectTab(Tab tab, int type, int lastId) {
if (mQueueController != null) {
mQueueController.dismissAllMessages();
}
}
};
......@@ -72,12 +86,14 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
* @param messageContainerCoordinator The coordinator able to show and hide message container.
* @param fullscreenManager The full screen manager able to notify the fullscreen mode change.
* @param layoutStateProviderOneShotSupplier Supplier of the {@link LayoutStateProvider}.
* @param tabModelSelectorSupplier Supplier of the {@link TabModelSelector}.
* @param messageDispatcher The {@link ManagedMessageDispatcher} able to suspend/resume queue.
*/
public ChromeMessageQueueMediator(BrowserControlsManager browserControlsManager,
MessageContainerCoordinator messageContainerCoordinator,
FullscreenManager fullscreenManager,
OneshotSupplier<LayoutStateProvider> layoutStateProviderOneShotSupplier,
ObservableSupplier<TabModelSelector> tabModelSelectorSupplier,
ManagedMessageDispatcher messageDispatcher) {
mBrowserControlsManager = browserControlsManager;
mContainerCoordinator = messageContainerCoordinator;
......@@ -87,6 +103,7 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
mBrowserControlsObserver = new BrowserControlsObserver();
mBrowserControlsManager.addObserver(mBrowserControlsObserver);
layoutStateProviderOneShotSupplier.onAvailable(this::setLayoutStateProvider);
tabModelSelectorSupplier.addObserver(this::setTabModelSelector);
}
public void destroy() {
......@@ -95,6 +112,11 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
if (mLayoutStateProvider != null) {
mLayoutStateProvider.removeObserver(mLayoutStateObserver);
}
if (mTabModelSelector != null) {
mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
mTabModelObserver);
}
mTabModelSelector = null;
mLayoutStateProvider = null;
mQueueController = null;
mContainerCoordinator = null;
......@@ -144,6 +166,11 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
mLayoutStateProvider.addObserver(mLayoutStateObserver);
}
private void setTabModelSelector(TabModelSelector tabModelSelector) {
mTabModelSelector = tabModelSelector;
mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(mTabModelObserver);
}
class BrowserControlsObserver implements BrowserControlsStateProvider.Observer {
private Runnable mRunOnControlsFullyVisible;
......
......@@ -402,10 +402,10 @@ public class RootUiCoordinator
new MessageContainerCoordinator(container, getBrowserControlsManager());
mMessageDispatcher = MessagesFactory.createMessageDispatcher(
container, mMessageContainerCoordinator::getMessageMaxTranslation);
mMessageQueueMediator =
new ChromeMessageQueueMediator(mActivity.getBrowserControlsManager(),
mMessageContainerCoordinator, mActivity.getFullscreenManager(),
mLayoutStateProviderOneShotSupplier, mMessageDispatcher);
mMessageQueueMediator = new ChromeMessageQueueMediator(
mActivity.getBrowserControlsManager(), mMessageContainerCoordinator,
mActivity.getFullscreenManager(), mLayoutStateProviderOneShotSupplier,
mTabModelSelectorSupplier, mMessageDispatcher);
mMessageDispatcher.setDelegate(mMessageQueueMediator);
MessagesFactory.attachMessageDispatcher(
mActivity.getWindowAndroid(), mMessageDispatcher);
......
......@@ -40,6 +40,11 @@ public class MessageDispatcherImpl implements ManagedMessageDispatcher {
mMessageQueueManager.dismissMessage(messageProperties);
}
@Override
public void dismissAllMessages() {
mMessageQueueManager.dismissAllMessages();
}
@Override
public int suspend() {
return mMessageQueueManager.suspend();
......
......@@ -5,6 +5,7 @@
package org.chromium.components.messages;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.ui.util.TokenHolder;
......@@ -99,4 +100,30 @@ class MessageQueueManager {
});
}
}
void dismissAllMessages() {
if (mCurrentDisplayedMessage != null) {
mMessageQueue.remove(mCurrentDisplayedMessage);
mCurrentDisplayedMessage.hide(false, () -> {
mMessageQueueDelegate.onFinishHiding();
mCurrentDisplayedMessage.dismiss();
mCurrentDisplayedMessage = null;
});
}
for (MessageStateHandler h : mMessageQueue) {
h.dismiss();
}
mMessageMap.clear();
mMessageQueue.clear();
}
@VisibleForTesting
Queue<MessageStateHandler> getMessageQueueForTesting() {
return mMessageQueue;
}
@VisibleForTesting
Map<Object, MessageStateHandler> getMessageMapForTesting() {
return mMessageMap;
}
}
......@@ -12,6 +12,7 @@ import static org.mockito.Mockito.verify;
import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
......@@ -151,6 +152,30 @@ public class MessageQueueManagerTest {
verify(m1, times(1)).dismiss();
}
/**
* Tests that all messages can be dismissed correctly.
*/
@Test
@SmallTest
public void testDismissAllMessages() {
MessageQueueManager queueManager = new MessageQueueManager();
queueManager.setDelegate(mEmptyDelegate);
final int count = 10;
MessageStateHandler handlers[] = new MessageStateHandler[count];
for (int i = 0; i < count; i++) {
handlers[i] = Mockito.spy(new EmptyMessageStateHandler());
queueManager.enqueueMessage(handlers[i], handlers[i]);
}
queueManager.dismissAllMessages();
for (MessageStateHandler h : handlers) {
verify(h).dismiss();
}
Assert.assertEquals("Map should be cleared after all messages are dismissed", 0,
queueManager.getMessageMapForTesting().size());
Assert.assertEquals("Queue should be cleared after all messages are dismissed", 0,
queueManager.getMessageQueueForTesting().size());
}
/**
* Tests that delegate methods are properly called when queue is suspended
* and resumed.
......
......@@ -26,4 +26,10 @@ public interface ManagedMessageDispatcher
* @param delegate The {@link MessageQueueDelegate}.
*/
void setDelegate(MessageQueueDelegate delegate);
/**
* Dismiss all the enqueued messages. The currently being displayed message will be
* hidden at once without animations.
*/
void dismissAllMessages();
}
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