[go: nahoru, domu]

blob: 53ee7971879eed4c2dff4ca6b1d1fbca850cb47d [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/picture_in_picture/picture_in_picture_session.h"
#include <utility>
#include "base/functional/callback_helpers.h"
#include "content/browser/picture_in_picture/picture_in_picture_service_impl.h"
#include "content/browser/picture_in_picture/video_picture_in_picture_window_controller_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
namespace content {
PictureInPictureSession::PictureInPictureSession(
PictureInPictureServiceImpl* service,
const MediaPlayerId& player_id,
mojo::PendingAssociatedRemote<media::mojom::MediaPlayer> player_remote,
mojo::PendingReceiver<blink::mojom::PictureInPictureSession> receiver,
mojo::PendingRemote<blink::mojom::PictureInPictureSessionObserver> observer)
: service_(service),
receiver_(this, std::move(receiver)),
player_id_(player_id),
media_player_remote_(std::move(player_remote)),
observer_(std::move(observer)) {
receiver_.set_disconnect_handler(base::BindOnce(
&PictureInPictureSession::OnConnectionError, base::Unretained(this)));
media_player_remote_.set_disconnect_handler(base::BindOnce(
&PictureInPictureSession::OnPlayerGone, base::Unretained(this)));
}
PictureInPictureSession::~PictureInPictureSession() {
DCHECK(is_stopping_);
}
void PictureInPictureSession::Stop(StopCallback callback) {
StopInternal(std::move(callback));
}
void PictureInPictureSession::Update(
uint32_t player_id,
mojo::PendingAssociatedRemote<media::mojom::MediaPlayer> player_remote,
const viz::SurfaceId& surface_id,
const gfx::Size& natural_size,
bool show_play_pause_button) {
player_id_ =
MediaPlayerId(service_->render_frame_host().GetGlobalId(), player_id);
media_player_remote_.reset();
media_player_remote_.Bind(std::move(player_remote));
media_player_remote_.set_disconnect_handler(base::BindOnce(
&PictureInPictureSession::OnPlayerGone, base::Unretained(this)));
GetController().EmbedSurface(surface_id, natural_size);
GetController().SetShowPlayPauseButton(show_play_pause_button);
}
void PictureInPictureSession::OnPlayerGone() {
player_id_.reset();
GetController().SetShowPlayPauseButton(false);
}
void PictureInPictureSession::NotifyWindowResized(const gfx::Size& size) {
observer_->OnWindowSizeChanged(size);
}
mojo::AssociatedRemote<media::mojom::MediaPlayer>&
PictureInPictureSession::GetMediaPlayerRemote() {
DCHECK(media_player_remote_.is_bound());
return media_player_remote_;
}
void PictureInPictureSession::Disconnect() {
// |is_stopping_| shouldn't be true for the implementation in //chrome but if
// the WebContentsDelegate's Picture-in-Picture calls are empty, it's possible
// for `Disconnect()` to be called even after `StopInternal()` as the
// expectation of self-destruction will no longer be true.
if (is_stopping_)
return;
is_stopping_ = true;
observer_->OnStopped();
}
void PictureInPictureSession::Shutdown() {
if (is_stopping_)
return;
StopInternal(base::NullCallback());
}
void PictureInPictureSession::StopInternal(StopCallback callback) {
DCHECK(!is_stopping_);
is_stopping_ = true;
// `OnStopped()` should only be called if there is no callback to run, as a
// contract in the API.
if (callback)
std::move(callback).Run();
else
observer_->OnStopped();
// |this| will be deleted after this call.
GetWebContentsImpl()->ExitPictureInPicture();
}
void PictureInPictureSession::OnConnectionError() {
// There is possibility that OnConnectionError arrives between StopInternal()
// is called and |this| is deleted. As a result, DCHECK in StopInternal()
// will fail.
if (is_stopping_)
return;
// StopInternal() will self destruct which will close the bindings.
StopInternal(base::NullCallback());
}
WebContentsImpl* PictureInPictureSession::GetWebContentsImpl() {
return static_cast<WebContentsImpl*>(
WebContents::FromRenderFrameHost(&service_->render_frame_host()));
}
VideoPictureInPictureWindowControllerImpl&
PictureInPictureSession::GetController() {
return *VideoPictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
GetWebContentsImpl());
}
} // namespace content