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 @@ ...@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.messages; package org.chromium.chrome.browser.messages;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.supplier.OneshotSupplier; import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils; import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils;
...@@ -15,6 +16,8 @@ import org.chromium.chrome.browser.layouts.LayoutStateProvider; ...@@ -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.LayoutStateProvider.LayoutStateObserver;
import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.layouts.LayoutType;
import org.chromium.chrome.browser.tab.Tab; 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.ManagedMessageDispatcher;
import org.chromium.components.messages.MessageQueueDelegate; import org.chromium.components.messages.MessageQueueDelegate;
import org.chromium.ui.util.TokenHolder; import org.chromium.ui.util.TokenHolder;
...@@ -32,6 +35,7 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate { ...@@ -32,6 +35,7 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
private int mBrowserControlsToken = TokenHolder.INVALID_TOKEN; private int mBrowserControlsToken = TokenHolder.INVALID_TOKEN;
private BrowserControlsObserver mBrowserControlsObserver; private BrowserControlsObserver mBrowserControlsObserver;
private LayoutStateProvider mLayoutStateProvider; private LayoutStateProvider mLayoutStateProvider;
private TabModelSelector mTabModelSelector;
private FullscreenManager.Observer mFullScreenObserver = new Observer() { private FullscreenManager.Observer mFullScreenObserver = new Observer() {
private int mToken = TokenHolder.INVALID_TOKEN; private int mToken = TokenHolder.INVALID_TOKEN;
...@@ -53,15 +57,25 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate { ...@@ -53,15 +57,25 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
@Override @Override
public void onStartedShowing(int layoutType, boolean showToolbar) { public void onStartedShowing(int layoutType, boolean showToolbar) {
if (layoutType == LayoutType.TAB_SWITCHER) { if (mToken == TokenHolder.INVALID_TOKEN && layoutType != LayoutType.BROWSING) {
mToken = suspendQueue(); mToken = suspendQueue();
} }
} }
@Override @Override
public void onFinishedHiding(int layoutType) { public void onFinishedHiding(int layoutType) {
if (layoutType == LayoutType.TAB_SWITCHER) { if (mToken != TokenHolder.INVALID_TOKEN && layoutType == LayoutType.BROWSING) {
resumeQueue(mToken); 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 { ...@@ -72,12 +86,14 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
* @param messageContainerCoordinator The coordinator able to show and hide message container. * @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 fullscreenManager The full screen manager able to notify the fullscreen mode change.
* @param layoutStateProviderOneShotSupplier Supplier of the {@link LayoutStateProvider}. * @param layoutStateProviderOneShotSupplier Supplier of the {@link LayoutStateProvider}.
* @param tabModelSelectorSupplier Supplier of the {@link TabModelSelector}.
* @param messageDispatcher The {@link ManagedMessageDispatcher} able to suspend/resume queue. * @param messageDispatcher The {@link ManagedMessageDispatcher} able to suspend/resume queue.
*/ */
public ChromeMessageQueueMediator(BrowserControlsManager browserControlsManager, public ChromeMessageQueueMediator(BrowserControlsManager browserControlsManager,
MessageContainerCoordinator messageContainerCoordinator, MessageContainerCoordinator messageContainerCoordinator,
FullscreenManager fullscreenManager, FullscreenManager fullscreenManager,
OneshotSupplier<LayoutStateProvider> layoutStateProviderOneShotSupplier, OneshotSupplier<LayoutStateProvider> layoutStateProviderOneShotSupplier,
ObservableSupplier<TabModelSelector> tabModelSelectorSupplier,
ManagedMessageDispatcher messageDispatcher) { ManagedMessageDispatcher messageDispatcher) {
mBrowserControlsManager = browserControlsManager; mBrowserControlsManager = browserControlsManager;
mContainerCoordinator = messageContainerCoordinator; mContainerCoordinator = messageContainerCoordinator;
...@@ -87,6 +103,7 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate { ...@@ -87,6 +103,7 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
mBrowserControlsObserver = new BrowserControlsObserver(); mBrowserControlsObserver = new BrowserControlsObserver();
mBrowserControlsManager.addObserver(mBrowserControlsObserver); mBrowserControlsManager.addObserver(mBrowserControlsObserver);
layoutStateProviderOneShotSupplier.onAvailable(this::setLayoutStateProvider); layoutStateProviderOneShotSupplier.onAvailable(this::setLayoutStateProvider);
tabModelSelectorSupplier.addObserver(this::setTabModelSelector);
} }
public void destroy() { public void destroy() {
...@@ -95,6 +112,11 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate { ...@@ -95,6 +112,11 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
if (mLayoutStateProvider != null) { if (mLayoutStateProvider != null) {
mLayoutStateProvider.removeObserver(mLayoutStateObserver); mLayoutStateProvider.removeObserver(mLayoutStateObserver);
} }
if (mTabModelSelector != null) {
mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
mTabModelObserver);
}
mTabModelSelector = null;
mLayoutStateProvider = null; mLayoutStateProvider = null;
mQueueController = null; mQueueController = null;
mContainerCoordinator = null; mContainerCoordinator = null;
...@@ -144,6 +166,11 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate { ...@@ -144,6 +166,11 @@ public class ChromeMessageQueueMediator implements MessageQueueDelegate {
mLayoutStateProvider.addObserver(mLayoutStateObserver); mLayoutStateProvider.addObserver(mLayoutStateObserver);
} }
private void setTabModelSelector(TabModelSelector tabModelSelector) {
mTabModelSelector = tabModelSelector;
mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(mTabModelObserver);
}
class BrowserControlsObserver implements BrowserControlsStateProvider.Observer { class BrowserControlsObserver implements BrowserControlsStateProvider.Observer {
private Runnable mRunOnControlsFullyVisible; private Runnable mRunOnControlsFullyVisible;
......
...@@ -402,10 +402,10 @@ public class RootUiCoordinator ...@@ -402,10 +402,10 @@ public class RootUiCoordinator
new MessageContainerCoordinator(container, getBrowserControlsManager()); new MessageContainerCoordinator(container, getBrowserControlsManager());
mMessageDispatcher = MessagesFactory.createMessageDispatcher( mMessageDispatcher = MessagesFactory.createMessageDispatcher(
container, mMessageContainerCoordinator::getMessageMaxTranslation); container, mMessageContainerCoordinator::getMessageMaxTranslation);
mMessageQueueMediator = mMessageQueueMediator = new ChromeMessageQueueMediator(
new ChromeMessageQueueMediator(mActivity.getBrowserControlsManager(), mActivity.getBrowserControlsManager(), mMessageContainerCoordinator,
mMessageContainerCoordinator, mActivity.getFullscreenManager(), mActivity.getFullscreenManager(), mLayoutStateProviderOneShotSupplier,
mLayoutStateProviderOneShotSupplier, mMessageDispatcher); mTabModelSelectorSupplier, mMessageDispatcher);
mMessageDispatcher.setDelegate(mMessageQueueMediator); mMessageDispatcher.setDelegate(mMessageQueueMediator);
MessagesFactory.attachMessageDispatcher( MessagesFactory.attachMessageDispatcher(
mActivity.getWindowAndroid(), mMessageDispatcher); mActivity.getWindowAndroid(), mMessageDispatcher);
......
...@@ -40,6 +40,11 @@ public class MessageDispatcherImpl implements ManagedMessageDispatcher { ...@@ -40,6 +40,11 @@ public class MessageDispatcherImpl implements ManagedMessageDispatcher {
mMessageQueueManager.dismissMessage(messageProperties); mMessageQueueManager.dismissMessage(messageProperties);
} }
@Override
public void dismissAllMessages() {
mMessageQueueManager.dismissAllMessages();
}
@Override @Override
public int suspend() { public int suspend() {
return mMessageQueueManager.suspend(); return mMessageQueueManager.suspend();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package org.chromium.components.messages; package org.chromium.components.messages;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.ui.util.TokenHolder; import org.chromium.ui.util.TokenHolder;
...@@ -99,4 +100,30 @@ class MessageQueueManager { ...@@ -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; ...@@ -12,6 +12,7 @@ import static org.mockito.Mockito.verify;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mockito; import org.mockito.Mockito;
...@@ -151,6 +152,30 @@ public class MessageQueueManagerTest { ...@@ -151,6 +152,30 @@ public class MessageQueueManagerTest {
verify(m1, times(1)).dismiss(); 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 * Tests that delegate methods are properly called when queue is suspended
* and resumed. * and resumed.
......
...@@ -26,4 +26,10 @@ public interface ManagedMessageDispatcher ...@@ -26,4 +26,10 @@ public interface ManagedMessageDispatcher
* @param delegate The {@link MessageQueueDelegate}. * @param delegate The {@link MessageQueueDelegate}.
*/ */
void setDelegate(MessageQueueDelegate delegate); 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