| Index: chrome/android/java/src/org/chromium/chrome/browser/media/ui/MediaSessionTabHelper.java
 | 
| 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 19252e1106b262e2fa3f854d5bc5f0e043cc2386..f58e2736d63c11b9aedc589b2a4c1b7dcc0a683d 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
 | 
| @@ -12,6 +12,7 @@ import android.text.TextUtils;
 | 
|  
 | 
|  import org.chromium.base.ContextUtils;
 | 
|  import org.chromium.base.Log;
 | 
| +import org.chromium.base.VisibleForTesting;
 | 
|  import org.chromium.chrome.R;
 | 
|  import org.chromium.chrome.browser.metrics.MediaNotificationUma;
 | 
|  import org.chromium.chrome.browser.metrics.MediaSessionUMA;
 | 
| @@ -19,14 +20,17 @@ import org.chromium.chrome.browser.tab.EmptyTabObserver;
 | 
|  import org.chromium.chrome.browser.tab.Tab;
 | 
|  import org.chromium.chrome.browser.tab.TabObserver;
 | 
|  import org.chromium.components.url_formatter.UrlFormatter;
 | 
| +import org.chromium.content.browser.ChromeMediaSession;
 | 
| +import org.chromium.content.browser.MediaSessionObserver;
 | 
|  import org.chromium.content_public.browser.WebContents;
 | 
| -import org.chromium.content_public.browser.WebContentsObserver;
 | 
|  import org.chromium.content_public.common.MediaMetadata;
 | 
|  import org.chromium.ui.base.WindowAndroid;
 | 
|  
 | 
|  import java.net.URI;
 | 
|  import java.net.URISyntaxException;
 | 
|  
 | 
| +import javax.annotation.Nullable;
 | 
| +
 | 
|  /**
 | 
|   * A tab helper responsible for enabling/disabling media controls and passing
 | 
|   * media actions from the controls to the {@link org.chromium.content.browser.MediaSession}
 | 
| @@ -42,8 +46,7 @@ public class MediaSessionTabHelper implements MediaImageCallback {
 | 
|      private Bitmap mFavicon = null;
 | 
|      private Bitmap mCurrentMediaImage = null;
 | 
|      private String mOrigin = null;
 | 
| -    private WebContents mWebContents;
 | 
| -    private WebContentsObserver mWebContentsObserver;
 | 
| +    private MediaSessionObserver mMediaSessionObserver;
 | 
|      private int mPreviousVolumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE;
 | 
|      private MediaNotificationInfo.Builder mNotificationInfoBuilder = null;
 | 
|      // The fallback title if |mPageMetadata| is null or its title is empty.
 | 
| @@ -54,29 +57,32 @@ public class MediaSessionTabHelper implements MediaImageCallback {
 | 
|      private MediaMetadata mCurrentMetadata = null;
 | 
|      private MediaImageManager mMediaImageManager = null;
 | 
|  
 | 
| +    @VisibleForTesting
 | 
| +    @Nullable
 | 
| +    MediaSessionObserver getMediaSessionObserverForTesting() {
 | 
| +        return mMediaSessionObserver;
 | 
| +    }
 | 
| +
 | 
|      private MediaNotificationListener mControlsListener = new MediaNotificationListener() {
 | 
|          @Override
 | 
|          public void onPlay(int actionSource) {
 | 
|              MediaSessionUMA
 | 
|                      .recordPlay(MediaSessionTabHelper.convertMediaActionSourceToUMA(actionSource));
 | 
| -
 | 
| -            mWebContents.resumeMediaSession();
 | 
| +            if (mMediaSessionObserver != null) mMediaSessionObserver.getSession().resume();
 | 
|          }
 | 
|  
 | 
|          @Override
 | 
|          public void onPause(int actionSource) {
 | 
|              MediaSessionUMA.recordPause(
 | 
|                      MediaSessionTabHelper.convertMediaActionSourceToUMA(actionSource));
 | 
| -
 | 
| -            mWebContents.suspendMediaSession();
 | 
| +            if (mMediaSessionObserver != null) mMediaSessionObserver.getSession().suspend();
 | 
|          }
 | 
|  
 | 
|          @Override
 | 
|          public void onStop(int actionSource) {
 | 
|              MediaSessionUMA
 | 
|                      .recordStop(MediaSessionTabHelper.convertMediaActionSourceToUMA(actionSource));
 | 
| -
 | 
| -            mWebContents.stopMediaSession();
 | 
| +            if (mMediaSessionObserver != null) mMediaSessionObserver.getSession().stop();
 | 
|          }
 | 
|      };
 | 
|  
 | 
| @@ -92,12 +98,11 @@ public class MediaSessionTabHelper implements MediaImageCallback {
 | 
|          mNotificationInfoBuilder = null;
 | 
|      }
 | 
|  
 | 
| -    private WebContentsObserver createWebContentsObserver(WebContents webContents) {
 | 
| -        return new WebContentsObserver(webContents) {
 | 
| +    private MediaSessionObserver createMediaSessionObserver(ChromeMediaSession session) {
 | 
| +        return new MediaSessionObserver(session) {
 | 
|              @Override
 | 
| -            public void destroy() {
 | 
| +            public void mediaSessionDestroyed() {
 | 
|                  hideNotification();
 | 
| -                super.destroy();
 | 
|              }
 | 
|  
 | 
|              @Override
 | 
| @@ -153,18 +158,23 @@ public class MediaSessionTabHelper implements MediaImageCallback {
 | 
|      }
 | 
|  
 | 
|      private void setWebContents(WebContents webContents) {
 | 
| -        if (mWebContents == webContents) return;
 | 
| +        ChromeMediaSession session = ChromeMediaSession.fromWebContents(webContents);
 | 
| +        if (mMediaSessionObserver != null && session == mMediaSessionObserver.getSession()) {
 | 
| +            return;
 | 
| +        }
 | 
|  
 | 
| -        cleanupWebContents();
 | 
| -        mWebContents = webContents;
 | 
| -        if (mWebContents != null) mWebContentsObserver = createWebContentsObserver(mWebContents);
 | 
| -        mMediaImageManager.setWebContents(mWebContents);
 | 
| +        cleanupMediaSessionObserver();
 | 
| +        if (webContents != null) {
 | 
| +            mMediaSessionObserver = createMediaSessionObserver(session);
 | 
| +        }
 | 
| +        mMediaImageManager.setWebContents(webContents);
 | 
|      }
 | 
|  
 | 
| -    private void cleanupWebContents() {
 | 
| -        if (mWebContentsObserver != null) mWebContentsObserver.destroy();
 | 
| -        mWebContentsObserver = null;
 | 
| -        mWebContents = null;
 | 
| +    private void cleanupMediaSessionObserver() {
 | 
| +        if (mMediaSessionObserver != null) {
 | 
| +            mMediaSessionObserver.getSession().removeObserver(mMediaSessionObserver);
 | 
| +        }
 | 
| +        mMediaSessionObserver = null;
 | 
|      }
 | 
|  
 | 
|      private final TabObserver mTabObserver = new EmptyTabObserver() {
 | 
| @@ -222,7 +232,7 @@ public class MediaSessionTabHelper implements MediaImageCallback {
 | 
|          public void onDestroyed(Tab tab) {
 | 
|              assert mTab == tab;
 | 
|  
 | 
| -            cleanupWebContents();
 | 
| +            cleanupMediaSessionObserver();
 | 
|  
 | 
|              hideNotification();
 | 
|              mTab.removeObserver(this);
 | 
| 
 |