diff options
author | zqzhang <zqzhang@chromium.org> | 2015-12-12 11:53:50 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-12 19:54:42 +0000 |
commit | d0b0d5fe705a29ff989dd3708d61154e8c600024 (patch) | |
tree | 7242765f12d8d309506d4858c16d25f13ef75d18 | |
parent | f696e12b2cb0f829849cf56974d3efa67b437512 (diff) | |
download | chromium_src-d0b0d5fe705a29ff989dd3708d61154e8c600024.zip chromium_src-d0b0d5fe705a29ff989dd3708d61154e8c600024.tar.gz chromium_src-d0b0d5fe705a29ff989dd3708d61154e8c600024.tar.bz2 |
Update media notification when page title changes
This CL makes the media notification keep in sync when the page title
changes.
BUG=550424
Review URL: https://codereview.chromium.org/1417743005
Cr-Commit-Position: refs/heads/master@{#364938}
7 files changed, 177 insertions, 3 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java index ad4bd08..90d84a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaNotificationManager.java @@ -327,6 +327,14 @@ public class MediaNotificationManager { return getManager(notificationId) != null; } + @VisibleForTesting + @Nullable + protected static MediaNotificationInfo getNotificationInfoForTesting(int notificationId) { + MediaNotificationManager manager = getManager(notificationId); + if (manager == null) return null; + return manager.mMediaNotificationInfo; + } + private final Context mContext; // ListenerService running for the notification. Only non-null when showing. diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java index 4dce275..b0f07d4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java @@ -142,6 +142,16 @@ public class MediaSessionTabHelper { } @Override + public void onTitleUpdated(Tab tab) { + assert tab == mTab; + if (mNotificationInfoBuilder == null) return; + + mNotificationInfoBuilder.setTitle(sanitizeMediaTitle(mTab.getTitle())); + MediaNotificationManager.show(ApplicationStatus.getApplicationContext(), + mNotificationInfoBuilder.build()); + } + + @Override public void onDestroyed(Tab tab) { assert mTab == tab; diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java new file mode 100644 index 0000000..d505fbe --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/NotificationTitleUpdatedTest.java @@ -0,0 +1,132 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.media.ui; + +import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; +import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_PHONE; + +import android.test.suitebuilder.annotation.SmallTest; + +import org.chromium.base.ObserverList; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.test.ChromeActivityTestCaseBase; +import org.chromium.chrome.test.util.browser.TabTitleObserver; +import org.chromium.content.browser.test.util.JavaScriptUtils; +import org.chromium.content_public.browser.WebContentsObserver; + +/** + * Test of media notifications to see whether the text updates when the tab title changes + */ +public class NotificationTitleUpdatedTest extends ChromeActivityTestCaseBase<ChromeActivity> { + private static final int NOTIFICATION_ID = R.id.media_playback_notification; + + private Tab mTab; + + public NotificationTitleUpdatedTest() { + super(ChromeActivity.class); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + mTab = getActivity().getActivityTab(); + simulateUpdateTitle(mTab, "title1"); + } + + @SmallTest + public void testSessionStatePlaying() throws InterruptedException { + simulateMediaSessionStateChanged(mTab, true, false); + assertTitleMatches("title1"); + simulateUpdateTitle(mTab, "title2"); + assertTitleMatches("title2"); + } + + @SmallTest + public void testSessionStatePaused() { + simulateMediaSessionStateChanged(mTab, true, true); + assertTitleMatches("title1"); + simulateUpdateTitle(mTab, "title2"); + assertTitleMatches("title2"); + } + + @SmallTest + public void testSessionStateUncontrollable() { + simulateMediaSessionStateChanged(mTab, true, false); + assertTitleMatches("title1"); + simulateMediaSessionStateChanged(mTab, false, false); + simulateUpdateTitle(mTab, "title2"); + } + + /** + * Test if a notification accepts the title update from another tab, using the following steps: + * 1. set the title of mTab, start the media session, a notification should show up; + * 2. stop the media session of mTab, the notification shall hide; + * 3. create newTab, set the title of mTab, start the media session of mTab, + * a notification should show up; + * 4. change the title of newTab and then mTab to different names, + * the notification should have the title of newTab. + */ + @SmallTest + @Restriction({RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE}) + public void testMultipleTabs() throws Throwable { + simulateMediaSessionStateChanged(mTab, true, false); + assertTitleMatches("title1"); + simulateMediaSessionStateChanged(mTab, false, false); + + Tab newTab = loadUrlInNewTab("about:blank"); + assertNotNull(newTab); + + simulateMediaSessionStateChanged(newTab, true, false); + simulateUpdateTitle(newTab, "title3"); + simulateUpdateTitle(mTab, "title2"); + assertTitleMatches("title3"); + } + + @Override + public void startMainActivity() throws InterruptedException { + startMainActivityOnBlankPage(); + } + + private void simulateMediaSessionStateChanged( + final Tab tab, final boolean isControllable, final boolean isSuspended) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + ObserverList.RewindableIterator<WebContentsObserver> observers = + tab.getWebContents().getObserversForTesting(); + while (observers.hasNext()) { + observers.next().mediaSessionStateChanged( + isControllable, isSuspended); + } + } + }); + } + + private void simulateUpdateTitle(Tab tab, String title) { + try { + TabTitleObserver observer = new TabTitleObserver(tab, title); + JavaScriptUtils.executeJavaScriptAndWaitForResult( + tab.getWebContents(), + "document.title = '" + title + "';"); + observer.waitForTitleUpdate(5); + } catch (Exception e) { + throw new RuntimeException(e + "failed to update title"); + } + } + + void assertTitleMatches(final String title) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + assertEquals(title, MediaNotificationManager + .getNotificationInfoForTesting(NOTIFICATION_ID).title); + } + }); + } +} diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java index 006b0d5..16a6b3a 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java @@ -352,8 +352,8 @@ public abstract class ChromeActivityTestCaseBase<T extends ChromeActivity> * Load a url in a new tab. The {@link Tab} will pretend to be created from a link. * @param url The url of the page to load. */ - public void loadUrlInNewTab(final String url) throws InterruptedException { - loadUrlInNewTab(url, false); + public Tab loadUrlInNewTab(final String url) throws InterruptedException { + return loadUrlInNewTab(url, false); } /** @@ -361,7 +361,7 @@ public abstract class ChromeActivityTestCaseBase<T extends ChromeActivity> * @param url The url of the page to load. * @param incognito Whether the new tab should be incognito. */ - public void loadUrlInNewTab(final String url, final boolean incognito) + public Tab loadUrlInNewTab(final String url, final boolean incognito) throws InterruptedException { Tab tab = null; if (FeatureUtilities.isDocumentMode(getInstrumentation().getContext())) { @@ -405,6 +405,7 @@ public abstract class ChromeActivityTestCaseBase<T extends ChromeActivity> } ChromeTabUtils.waitForTabPageLoaded(tab, url); getInstrumentation().waitForIdleSync(); + return tab; } /** diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java index e2d6cef..04c3745 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java @@ -12,6 +12,7 @@ import android.os.Parcel; import android.os.ParcelUuid; import android.os.Parcelable; +import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; @@ -425,6 +426,12 @@ import java.util.UUID; mObserverProxy.removeObserver(observer); } + @VisibleForTesting + @Override + public ObserverList.RewindableIterator<WebContentsObserver> getObserversForTesting() { + return mObserverProxy.getObserversForTesting(); + } + @Override public void getContentBitmapAsync(Bitmap.Config config, float scale, Rect srcRect, ContentBitmapCallback callback) { diff --git a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java index 1c36430..9521812 100644 --- a/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java +++ b/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java @@ -7,6 +7,7 @@ package org.chromium.content.browser.webcontents; import org.chromium.base.ObserverList; import org.chromium.base.ObserverList.RewindableIterator; import org.chromium.base.ThreadUtils; +import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.MainDex; @@ -61,6 +62,14 @@ class WebContentsObserverProxy extends WebContentsObserver { return !mObservers.isEmpty(); } + /** + * @return The list of proxied observers. + */ + @VisibleForTesting + public ObserverList.RewindableIterator<WebContentsObserver> getObserversForTesting() { + return mObservers.rewindableIterator(); + } + @Override @CalledByNative public void renderViewReady() { diff --git a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java index 4a1729b..e58dd60 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/WebContents.java @@ -8,6 +8,7 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.os.Parcelable; +import org.chromium.base.ObserverList; import org.chromium.base.VisibleForTesting; /** @@ -323,6 +324,12 @@ public interface WebContents extends Parcelable { void removeObserver(WebContentsObserver observer); /** + * @return The list of observers. + */ + @VisibleForTesting + ObserverList.RewindableIterator<WebContentsObserver> getObserversForTesting(); + + /** * Called when context menu gets opened. */ void onContextMenuOpened(); |