1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/picture_in_picture/picture_in_picture_session.h"
6 
7 #include <utility>
8 
9 #include "base/bind_helpers.h"
10 #include "content/browser/picture_in_picture/picture_in_picture_service_impl.h"
11 #include "content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h"
12 #include "content/browser/web_contents/web_contents_impl.h"
13 
14 namespace content {
15 
PictureInPictureSession(PictureInPictureServiceImpl * service,const MediaPlayerId & player_id,const base::Optional<viz::SurfaceId> & surface_id,const gfx::Size & natural_size,bool show_play_pause_button,mojo::PendingReceiver<blink::mojom::PictureInPictureSession> receiver,mojo::PendingRemote<blink::mojom::PictureInPictureSessionObserver> observer,gfx::Size * window_size)16 PictureInPictureSession::PictureInPictureSession(
17     PictureInPictureServiceImpl* service,
18     const MediaPlayerId& player_id,
19     const base::Optional<viz::SurfaceId>& surface_id,
20     const gfx::Size& natural_size,
21     bool show_play_pause_button,
22     mojo::PendingReceiver<blink::mojom::PictureInPictureSession> receiver,
23     mojo::PendingRemote<blink::mojom::PictureInPictureSessionObserver> observer,
24     gfx::Size* window_size)
25     : service_(service),
26       receiver_(this, std::move(receiver)),
27       player_id_(player_id),
28       observer_(std::move(observer)) {
29   receiver_.set_disconnect_handler(base::BindOnce(
30       &PictureInPictureSession::OnConnectionError, base::Unretained(this)));
31 
32   GetController().SetActiveSession(this);
33   GetController().EmbedSurface(surface_id.value(), natural_size);
34   GetController().SetAlwaysHidePlayPauseButton(show_play_pause_button);
35   GetController().Show();
36 
37   *window_size = GetController().GetSize();
38 }
39 
~PictureInPictureSession()40 PictureInPictureSession::~PictureInPictureSession() {
41   DCHECK(is_stopping_);
42 }
43 
Stop(StopCallback callback)44 void PictureInPictureSession::Stop(StopCallback callback) {
45   StopInternal(std::move(callback));
46 }
47 
Update(uint32_t player_id,const base::Optional<viz::SurfaceId> & surface_id,const gfx::Size & natural_size,bool show_play_pause_button)48 void PictureInPictureSession::Update(
49     uint32_t player_id,
50     const base::Optional<viz::SurfaceId>& surface_id,
51     const gfx::Size& natural_size,
52     bool show_play_pause_button) {
53   player_id_ = MediaPlayerId(service_->render_frame_host_, player_id);
54 
55   GetController().EmbedSurface(surface_id.value(), natural_size);
56   GetController().SetAlwaysHidePlayPauseButton(show_play_pause_button);
57   GetController().SetActiveSession(this);
58 }
59 
NotifyWindowResized(const gfx::Size & size)60 void PictureInPictureSession::NotifyWindowResized(const gfx::Size& size) {
61   observer_->OnWindowSizeChanged(size);
62 }
63 
Shutdown()64 void PictureInPictureSession::Shutdown() {
65   if (is_stopping_)
66     return;
67 
68   StopInternal(base::NullCallback());
69 }
70 
StopInternal(StopCallback callback)71 void PictureInPictureSession::StopInternal(StopCallback callback) {
72   DCHECK(!is_stopping_);
73 
74   is_stopping_ = true;
75 
76   GetWebContentsImpl()->ExitPictureInPicture();
77 
78   // `OnStopped()` should only be called if there is no callback to run, as a
79   // contract in the API.
80   if (callback)
81     std::move(callback).Run();
82   else
83     observer_->OnStopped();
84 
85   GetController().SetActiveSession(nullptr);
86 
87   // Reset must happen after everything is done as it will destroy |this|.
88   service_->active_session_.reset();
89 }
90 
OnConnectionError()91 void PictureInPictureSession::OnConnectionError() {
92   // StopInternal() will self destruct which will close the bindings.
93   StopInternal(base::NullCallback());
94 }
95 
GetWebContentsImpl()96 WebContentsImpl* PictureInPictureSession::GetWebContentsImpl() {
97   return static_cast<WebContentsImpl*>(
98       WebContents::FromRenderFrameHost(service_->render_frame_host()));
99 }
100 
GetController()101 PictureInPictureWindowControllerImpl& PictureInPictureSession::GetController() {
102   return *PictureInPictureWindowControllerImpl::GetOrCreateForWebContents(
103       GetWebContentsImpl());
104 }
105 
106 }  // namespace content
107