diff options
Diffstat (limited to 'chromium/content/browser/media/session')
5 files changed, 61 insertions, 28 deletions
diff --git a/chromium/content/browser/media/session/media_session_android.cc b/chromium/content/browser/media/session/media_session_android.cc index 0df088b19cd..87c39dfcd09 100644 --- a/chromium/content/browser/media/session/media_session_android.cc +++ b/chromium/content/browser/media/session/media_session_android.cc @@ -38,9 +38,14 @@ MediaSessionAndroid::MediaSessionAndroid(MediaSessionImpl* session) Java_MediaSessionImpl_create(env, reinterpret_cast<intptr_t>(this)); j_media_session_ = JavaObjectWeakGlobalRef(env, j_media_session); - WebContentsAndroid* contents_android = GetWebContentsAndroid(); - if (contents_android) - contents_android->SetMediaSession(j_media_session); + WebContentsImpl* contents = + static_cast<WebContentsImpl*>(media_session_->web_contents()); + if (contents) { + web_contents_android_ = contents->GetWebContentsAndroid(); + DCHECK(web_contents_android_); + web_contents_android_->SetMediaSession(j_media_session); + web_contents_android_->AddDestructionObserver(this); + } session->AddObserver(observer_receiver_.BindNewPipeAndPassRemote()); } @@ -55,9 +60,10 @@ MediaSessionAndroid::~MediaSessionAndroid() { j_media_session_.reset(); - WebContentsAndroid* contents_android = GetWebContentsAndroid(); - if (contents_android) - contents_android->SetMediaSession(nullptr); + if (web_contents_android_) { + web_contents_android_->SetMediaSession(nullptr); + web_contents_android_->RemoveDestructionObserver(this); + } } // static @@ -71,7 +77,7 @@ ScopedJavaLocalRef<jobject> JNI_MediaSessionImpl_GetMediaSessionFromWebContents( MediaSessionImpl* session = MediaSessionImpl::Get(contents); DCHECK(session); return MediaSessionAndroid::JavaObjectGetter::GetJavaObject( - session->session_android()); + session->GetMediaSessionAndroid()); } void MediaSessionAndroid::MediaSessionInfoChanged( @@ -173,6 +179,14 @@ void MediaSessionAndroid::MediaSessionPositionChanged( } } +// The Java MediaSession is kept alive by the Java WebContents and will be +// cleared when the WebContents is destroyed, so we destroy the corresponding +// MediaSessionAndroid to ensure mediaSessionDestroyed is called. +void MediaSessionAndroid::WebContentsAndroidDestroyed( + WebContentsAndroid* web_contents_android) { + media_session_->ClearMediaSessionAndroid(); // Deletes |this|. +} + void MediaSessionAndroid::Resume( JNIEnv* env, const base::android::JavaParamRef<jobject>& j_obj) { @@ -228,14 +242,6 @@ void MediaSessionAndroid::RequestSystemAudioFocus( media_session::mojom::AudioFocusType::kGain); } -WebContentsAndroid* MediaSessionAndroid::GetWebContentsAndroid() { - WebContentsImpl* contents = - static_cast<WebContentsImpl*>(media_session_->web_contents()); - if (!contents) - return nullptr; - return contents->GetWebContentsAndroid(); -} - ScopedJavaLocalRef<jobject> MediaSessionAndroid::GetJavaObject() { JNIEnv* env = base::android::AttachCurrentThread(); return j_media_session_.get(env); diff --git a/chromium/content/browser/media/session/media_session_android.h b/chromium/content/browser/media/session/media_session_android.h index 2c7c2d95f84..b7fd9bdede6 100644 --- a/chromium/content/browser/media/session/media_session_android.h +++ b/chromium/content/browser/media/session/media_session_android.h @@ -11,20 +11,21 @@ #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" +#include "content/browser/web_contents/web_contents_android.h" #include "mojo/public/cpp/bindings/receiver.h" #include "services/media_session/public/mojom/media_session.mojom.h" namespace content { class MediaSessionImpl; -class WebContentsAndroid; // This class is interlayer between native MediaSession and Java // MediaSession. This class is owned by the native MediaSession and will // teardown Java MediaSession when the native MediaSession is destroyed. // Java MediaSessionObservers are also proxied via this class. class MediaSessionAndroid final - : public media_session::mojom::MediaSessionObserver { + : public media_session::mojom::MediaSessionObserver, + public WebContentsAndroid::DestructionObserver { public: // Helper class for calling GetJavaObject() in a static method, in order to // avoid leaking the Java object outside. @@ -48,6 +49,12 @@ class MediaSessionAndroid final void MediaSessionPositionChanged( const base::Optional<media_session::MediaPosition>& position) override; + // WebContentsAndroid::DestructionObserver overrides: + // TODO(crbug.com/1091229): Remove this when we correctly support media + // sessions in portals. + void WebContentsAndroidDestroyed( + WebContentsAndroid* web_contents_android) override; + // MediaSession method wrappers. void Resume(JNIEnv* env, const base::android::JavaParamRef<jobject>& j_obj); void Suspend(JNIEnv* env, const base::android::JavaParamRef<jobject>& j_obj); @@ -66,13 +73,14 @@ class MediaSessionAndroid final const base::android::JavaParamRef<jobject>& j_obj); private: - WebContentsAndroid* GetWebContentsAndroid(); - base::android::ScopedJavaLocalRef<jobject> GetJavaObject(); // The linked Java object. The strong reference is hold by Java WebContensImpl // to avoid introducing a new GC root. JavaObjectWeakGlobalRef j_media_session_; + // WebContentsAndroid corresponding to the Java WebContentsImpl that holds a + // strong reference to |j_media_session_|. + WebContentsAndroid* web_contents_android_; MediaSessionImpl* const media_session_; diff --git a/chromium/content/browser/media/session/media_session_impl.cc b/chromium/content/browser/media/session/media_session_impl.cc index e26a08c2b86..a364a0497c7 100644 --- a/chromium/content/browser/media/session/media_session_impl.cc +++ b/chromium/content/browser/media/session/media_session_impl.cc @@ -225,6 +225,22 @@ MediaSessionImpl::~MediaSessionImpl() { DCHECK(audio_focus_state_ == State::INACTIVE); } +#if defined(OS_ANDROID) +void MediaSessionImpl::ClearMediaSessionAndroid() { + session_android_.reset(); +} + +MediaSessionAndroid* MediaSessionImpl::GetMediaSessionAndroid() { + // |session_android_| can be null if a portal is activated, the java + // WebContents is destroyed and ClearMediaSessionAndroid is called. + // TODO(crbug.com/1091229): Remove this when we correctly support media + // sessions in portals. + if (!session_android_) + session_android_ = std::make_unique<MediaSessionAndroid>(this); + return session_android_.get(); +} +#endif + void MediaSessionImpl::WebContentsDestroyed() { // This should only work for tests. In production, all the players should have // already been removed before WebContents is destroyed. @@ -280,6 +296,7 @@ void MediaSessionImpl::TitleWasSet(NavigationEntry* entry) { } void MediaSessionImpl::DidUpdateFaviconURL( + RenderFrameHost* rfh, const std::vector<blink::mojom::FaviconURLPtr>& candidates) { std::vector<media_session::MediaImage> icons; @@ -831,7 +848,6 @@ MediaSessionImpl::MediaSessionImpl(WebContents* web_contents) #if defined(OS_ANDROID) session_android_.reset(new MediaSessionAndroid(this)); #endif // defined(OS_ANDROID) - if (web_contents && web_contents->GetMainFrame() && web_contents->GetMainFrame()->GetView()) { focused_ = web_contents->GetMainFrame()->GetView()->HasFocus(); @@ -845,7 +861,8 @@ void MediaSessionImpl::Initialize() { delegate_->MediaSessionInfoChanged(GetMediaSessionInfoSync()); DCHECK(web_contents()); - DidUpdateFaviconURL(web_contents()->GetFaviconURLs()); + DidUpdateFaviconURL(web_contents()->GetMainFrame(), + web_contents()->GetFaviconURLs()); } AudioFocusDelegate::AudioFocusResult MediaSessionImpl::RequestSystemAudioFocus( diff --git a/chromium/content/browser/media/session/media_session_impl.h b/chromium/content/browser/media/session/media_session_impl.h index 6ec74d5a2e1..a4c9bfed80a 100644 --- a/chromium/content/browser/media/session/media_session_impl.h +++ b/chromium/content/browser/media/session/media_session_impl.h @@ -85,11 +85,8 @@ class MediaSessionImpl : public MediaSession, ~MediaSessionImpl() override; #if defined(OS_ANDROID) - static MediaSession* FromJavaMediaSession( - const base::android::JavaRef<jobject>& j_media_session); - MediaSessionAndroid* session_android() const { - return session_android_.get(); - } + void ClearMediaSessionAndroid(); + MediaSessionAndroid* GetMediaSessionAndroid(); #endif // defined(OS_ANDROID) void NotifyMediaSessionMetadataChange(); @@ -139,6 +136,7 @@ class MediaSessionImpl : public MediaSession, void OnWebContentsLostFocus(RenderWidgetHost*) override; void TitleWasSet(NavigationEntry* entry) override; void DidUpdateFaviconURL( + RenderFrameHost* rfh, const std::vector<blink::mojom::FaviconURLPtr>& candidates) override; void MediaPictureInPictureChanged(bool is_picture_in_picture) override; diff --git a/chromium/content/browser/media/session/media_session_impl_browsertest.cc b/chromium/content/browser/media/session/media_session_impl_browsertest.cc index 77161c71d44..255ea2f601e 100644 --- a/chromium/content/browser/media/session/media_session_impl_browsertest.cc +++ b/chromium/content/browser/media/session/media_session_impl_browsertest.cc @@ -2514,7 +2514,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UpdateFaviconURL) { GURL("https://www.example.org/favicon6.png"), blink::mojom::FaviconIconType::kTouchIcon, std::vector<gfx::Size>())); - media_session_->DidUpdateFaviconURL(favicons); + media_session_->DidUpdateFaviconURL(shell()->web_contents()->GetMainFrame(), + favicons); { std::vector<media_session::MediaImage> expected_images; @@ -2542,6 +2543,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, UpdateFaviconURL) { { media_session::test::MockMediaSessionMojoObserver observer(*media_session_); media_session_->DidUpdateFaviconURL( + shell()->web_contents()->GetMainFrame(), std::vector<blink::mojom::FaviconURLPtr>()); observer.WaitForExpectedImagesOfType( media_session::mojom::MediaSessionImageType::kSourceIcon, @@ -2556,7 +2558,8 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, GURL("https://www.example.org/favicon1.png"), blink::mojom::FaviconIconType::kFavicon, std::vector<gfx::Size>())); - media_session_->DidUpdateFaviconURL(favicons); + media_session_->DidUpdateFaviconURL(shell()->web_contents()->GetMainFrame(), + favicons); { std::vector<media_session::MediaImage> expected_images; @@ -2607,6 +2610,7 @@ class FaviconWaiter : public WebContentsObserver { : WebContentsObserver(web_contents) {} void DidUpdateFaviconURL( + RenderFrameHost* render_frame_host, const std::vector<blink::mojom::FaviconURLPtr>& candidates) override { received_favicon_ = true; run_loop_.Quit(); |