| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 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 "chrome/browser/media/router/media_remoting_connector.h" |
| 6 |
| 7 #include "chrome/browser/media/router/media_remoting_provider.h" |
| 8 #include "mojo/public/cpp/bindings/strong_binding.h" |
| 9 |
| 10 DEFINE_WEB_CONTENTS_USER_DATA_KEY(media_router::MediaRemotingConnector); |
| 11 |
| 12 using content::RenderFrameHost; |
| 13 using content::WebContents; |
| 14 |
| 15 namespace media_router { |
| 16 |
| 17 class MediaRemotingConnector::FrameMediaRemoter : public media::mojom::Remoter { |
| 18 public: |
| 19 // |render_frame_host| represents the source frame for the remoted |
| 20 // media. Binds |this| to the given Mojo interface |request|. |
| 21 FrameMediaRemoter(RenderFrameHost* render_frame_host, |
| 22 mojo::InterfaceRequest<media::mojom::Remoter> request) |
| 23 : host_(render_frame_host), |
| 24 binding_(this, std::move(request)) { |
| 25 DCHECK(host_); |
| 26 } |
| 27 |
| 28 ~FrameMediaRemoter() final { |
| 29 if (client_.is_bound()) { |
| 30 if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) |
| 31 connector->DeregisterFrameRemoter(this); |
| 32 client_.reset(); |
| 33 } |
| 34 } |
| 35 |
| 36 media::mojom::RemoterClient* client() const { return client_.get(); } |
| 37 |
| 38 void OnMessageFromRemote(mojo::Array<uint8_t> message) { |
| 39 client_->OnMessageFromRemote(std::move(message)); |
| 40 } |
| 41 |
| 42 // media::mojom::Remoter implementation. |
| 43 |
| 44 void RegisterClient(media::mojom::RemoterClientPtr client) final { |
| 45 WebContents* const contents = WebContents::FromRenderFrameHost(host_); |
| 46 if (!contents) |
| 47 return; |
| 48 |
| 49 MediaRemotingConnector* const connector = |
| 50 MediaRemotingConnector::Get(contents); |
| 51 if (client_.is_bound()) |
| 52 connector->DeregisterFrameRemoter(this); |
| 53 client_ = std::move(client); |
| 54 if (client_.is_bound()) { |
| 55 client_.set_connection_error_handler(base::Bind( |
| 56 &FrameMediaRemoter::OnConnectionError, base::Unretained(this))); |
| 57 connector->RegisterFrameRemoter(this); |
| 58 } |
| 59 } |
| 60 |
| 61 void StartMediaServices(mojo::ScopedDataPipeConsumerHandle audio_pipe, |
| 62 mojo::ScopedDataPipeConsumerHandle video_pipe, |
| 63 const StartMediaServicesCallback& callback) final { |
| 64 if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) { |
| 65 connector->StartMediaServices( |
| 66 this, std::move(audio_pipe), std::move(video_pipe), callback); |
| 67 return; |
| 68 } |
| 69 callback.Run(false, MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID); |
| 70 } |
| 71 |
| 72 void StopMediaServices(const mojo::String& error_reason) final { |
| 73 if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) |
| 74 connector->StopMediaServices(this, error_reason); |
| 75 } |
| 76 |
| 77 void SendMessageToRemote(mojo::Array<uint8_t> message) final { |
| 78 if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) |
| 79 connector->SendMessageToRemote(this, std::move(message)); |
| 80 } |
| 81 |
| 82 void SendBufferToRemote(uint32_t pipe_id, |
| 83 media::mojom::DecoderBufferPtr buffer) final { |
| 84 if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) |
| 85 connector->SendBufferToRemote(this, pipe_id, std::move(buffer)); |
| 86 } |
| 87 |
| 88 private: |
| 89 void OnConnectionError() { |
| 90 if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) |
| 91 connector->DeregisterFrameRemoter(this); |
| 92 } |
| 93 |
| 94 RenderFrameHost* const host_; |
| 95 const mojo::StrongBinding<media::mojom::Remoter> binding_; |
| 96 |
| 97 media::mojom::RemoterClientPtr client_; |
| 98 |
| 99 DISALLOW_COPY_AND_ASSIGN(FrameMediaRemoter); |
| 100 }; |
| 101 |
| 102 // static |
| 103 MediaRemotingConnector* MediaRemotingConnector::Get(WebContents* contents) { |
| 104 MediaRemotingConnector* connector = FromWebContents(contents); |
| 105 if (connector) |
| 106 return connector; |
| 107 connector = new MediaRemotingConnector(contents); |
| 108 // The following transfers ownership of |connector| to WebContents. |
| 109 contents->SetUserData(UserDataKey(), connector); |
| 110 return connector; |
| 111 } |
| 112 |
| 113 // static |
| 114 MediaRemotingConnector* MediaRemotingConnector::GetIfExists( |
| 115 RenderFrameHost* render_frame_host) { |
| 116 if (auto* contents = WebContents::FromRenderFrameHost(render_frame_host)) |
| 117 return FromWebContents(contents); |
| 118 return nullptr; |
| 119 } |
| 120 |
| 121 // static |
| 122 void MediaRemotingConnector::CreateRemoter( |
| 123 RenderFrameHost* render_frame_host, |
| 124 mojo::InterfaceRequest<media::mojom::Remoter> request) { |
| 125 // The FrameMediaRemoter instance self-destructs when the bound pipe |
| 126 // encounters an error or is closed on the other end. |
| 127 new FrameMediaRemoter(render_frame_host, std::move(request)); |
| 128 } |
| 129 |
| 130 MediaRemotingConnector::MediaRemotingConnector(WebContents* contents) |
| 131 : provider_(nullptr), active_remoter_(nullptr) {} |
| 132 |
| 133 MediaRemotingConnector::~MediaRemotingConnector() { |
| 134 if (provider_) |
| 135 SetProvider(nullptr); |
| 136 } |
| 137 |
| 138 void MediaRemotingConnector::SetProvider(MediaRemotingProvider* provider) { |
| 139 // Disconnect the prior provider. |
| 140 if (provider_) { |
| 141 for (FrameMediaRemoter* remoter : remoters_) { |
| 142 if (auto* client = remoter->client()) |
| 143 client->OnRemoteServicesGone(); |
| 144 } |
| 145 if (active_remoter_) |
| 146 StopMediaServices(active_remoter_, mojo::String(nullptr)); |
| 147 } |
| 148 |
| 149 provider_ = provider; |
| 150 |
| 151 // Notify the RemoterClients that a new provider of remoting services is |
| 152 // available and ready. |
| 153 if (provider_) { |
| 154 auto* const capabilities = provider_->GetRemoteCapabilities(); |
| 155 DCHECK(capabilities); |
| 156 for (FrameMediaRemoter* remoter : remoters_) { |
| 157 if (auto* client = remoter->client()) |
| 158 client->OnRemoteServicesAvailable(capabilities->Clone()); |
| 159 } |
| 160 } |
| 161 } |
| 162 |
| 163 void MediaRemotingConnector::RegisterFrameRemoter(FrameMediaRemoter* remoter) { |
| 164 DCHECK(remoters_.find(remoter) == remoters_.end()); |
| 165 DCHECK(remoter->client()); |
| 166 remoters_.insert(remoter); |
| 167 if (provider_) { |
| 168 auto* const capabilities = provider_->GetRemoteCapabilities(); |
| 169 DCHECK(capabilities); |
| 170 remoter->client()->OnRemoteServicesAvailable(capabilities->Clone()); |
| 171 } |
| 172 } |
| 173 |
| 174 void MediaRemotingConnector::DeregisterFrameRemoter( |
| 175 FrameMediaRemoter* remoter) { |
| 176 if (auto* client = remoter->client()) |
| 177 client->OnRemoteServicesGone(); |
| 178 if (remoter == active_remoter_) |
| 179 StopMediaServices(remoter, mojo::String(nullptr)); |
| 180 remoters_.erase(remoter); |
| 181 } |
| 182 |
| 183 void MediaRemotingConnector::StartMediaServices( |
| 184 FrameMediaRemoter* remoter, |
| 185 mojo::ScopedDataPipeConsumerHandle audio_pipe, |
| 186 mojo::ScopedDataPipeConsumerHandle video_pipe, |
| 187 const base::Callback<void(bool, uint32_t, uint32_t)>& callback) { |
| 188 DCHECK(remoters_.find(remoter) != remoters_.end()); |
| 189 DCHECK(remoter->client()); |
| 190 const uint32_t audio_pipe_id = audio_pipe->value(); |
| 191 const uint32_t video_pipe_id = video_pipe->value(); |
| 192 if (!active_remoter_ && provider_ && |
| 193 provider_->StartMediaServices( |
| 194 std::move(audio_pipe), std::move(video_pipe), |
| 195 base::Bind(&FrameMediaRemoter::OnMessageFromRemote, |
| 196 base::Unretained(remoter)))) { |
| 197 active_remoter_ = remoter; |
| 198 DCHECK_NE(audio_pipe_id, video_pipe_id); |
| 199 callback.Run(true, audio_pipe_id, video_pipe_id); |
| 200 return; |
| 201 } |
| 202 callback.Run(false, MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID); |
| 203 } |
| 204 |
| 205 void MediaRemotingConnector::StopMediaServices( |
| 206 FrameMediaRemoter* remoter, const mojo::String& error_reason) { |
| 207 if (active_remoter_ != remoter) |
| 208 return; |
| 209 if (provider_) |
| 210 provider_->StopMediaServices(error_reason); |
| 211 active_remoter_ = nullptr; |
| 212 if (auto* client = remoter->client()) |
| 213 client->OnMediaServicesStopped(""); |
| 214 } |
| 215 |
| 216 void MediaRemotingConnector::SendMessageToRemote( |
| 217 FrameMediaRemoter* remoter, mojo::Array<uint8_t> message) { |
| 218 if (active_remoter_ != remoter || !provider_) |
| 219 return; |
| 220 provider_->SendMessageToRemote(std::move(message)); |
| 221 } |
| 222 |
| 223 void MediaRemotingConnector::SendBufferToRemote( |
| 224 FrameMediaRemoter* remoter, uint32_t pipe_id, |
| 225 media::mojom::DecoderBufferPtr buffer) { |
| 226 if (active_remoter_ != remoter || !provider_) |
| 227 return; |
| 228 provider_->SendBufferToRemote(pipe_id, std::move(buffer)); |
| 229 } |
| 230 |
| 231 } // namespace media_router |
| OLD | NEW |