| Index: chrome/browser/media/router/media_remoting_connector.cc
|
| diff --git a/chrome/browser/media/router/media_remoting_connector.cc b/chrome/browser/media/router/media_remoting_connector.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3de578657e2e92eaf6842d18f36963eefe12ff62
|
| --- /dev/null
|
| +++ b/chrome/browser/media/router/media_remoting_connector.cc
|
| @@ -0,0 +1,231 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/media/router/media_remoting_connector.h"
|
| +
|
| +#include "chrome/browser/media/router/media_remoting_provider.h"
|
| +#include "mojo/public/cpp/bindings/strong_binding.h"
|
| +
|
| +DEFINE_WEB_CONTENTS_USER_DATA_KEY(media_router::MediaRemotingConnector);
|
| +
|
| +using content::RenderFrameHost;
|
| +using content::WebContents;
|
| +
|
| +namespace media_router {
|
| +
|
| +class MediaRemotingConnector::FrameMediaRemoter : public media::mojom::Remoter {
|
| + public:
|
| + // |render_frame_host| represents the source frame for the remoted
|
| + // media. Binds |this| to the given Mojo interface |request|.
|
| + FrameMediaRemoter(RenderFrameHost* render_frame_host,
|
| + mojo::InterfaceRequest<media::mojom::Remoter> request)
|
| + : host_(render_frame_host),
|
| + binding_(this, std::move(request)) {
|
| + DCHECK(host_);
|
| + }
|
| +
|
| + ~FrameMediaRemoter() final {
|
| + if (client_.is_bound()) {
|
| + if (auto* connector = MediaRemotingConnector::GetIfExists(host_))
|
| + connector->DeregisterFrameRemoter(this);
|
| + client_.reset();
|
| + }
|
| + }
|
| +
|
| + media::mojom::RemoterClient* client() const { return client_.get(); }
|
| +
|
| + void OnMessageFromRemote(mojo::Array<uint8_t> message) {
|
| + client_->OnMessageFromRemote(std::move(message));
|
| + }
|
| +
|
| + // media::mojom::Remoter implementation.
|
| +
|
| + void RegisterClient(media::mojom::RemoterClientPtr client) final {
|
| + WebContents* const contents = WebContents::FromRenderFrameHost(host_);
|
| + if (!contents)
|
| + return;
|
| +
|
| + MediaRemotingConnector* const connector =
|
| + MediaRemotingConnector::Get(contents);
|
| + if (client_.is_bound())
|
| + connector->DeregisterFrameRemoter(this);
|
| + client_ = std::move(client);
|
| + if (client_.is_bound()) {
|
| + client_.set_connection_error_handler(base::Bind(
|
| + &FrameMediaRemoter::OnConnectionError, base::Unretained(this)));
|
| + connector->RegisterFrameRemoter(this);
|
| + }
|
| + }
|
| +
|
| + void StartMediaServices(mojo::ScopedDataPipeConsumerHandle audio_pipe,
|
| + mojo::ScopedDataPipeConsumerHandle video_pipe,
|
| + const StartMediaServicesCallback& callback) final {
|
| + if (auto* connector = MediaRemotingConnector::GetIfExists(host_)) {
|
| + connector->StartMediaServices(
|
| + this, std::move(audio_pipe), std::move(video_pipe), callback);
|
| + return;
|
| + }
|
| + callback.Run(false, MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID);
|
| + }
|
| +
|
| + void StopMediaServices(const mojo::String& error_reason) final {
|
| + if (auto* connector = MediaRemotingConnector::GetIfExists(host_))
|
| + connector->StopMediaServices(this, error_reason);
|
| + }
|
| +
|
| + void SendMessageToRemote(mojo::Array<uint8_t> message) final {
|
| + if (auto* connector = MediaRemotingConnector::GetIfExists(host_))
|
| + connector->SendMessageToRemote(this, std::move(message));
|
| + }
|
| +
|
| + void SendBufferToRemote(uint32_t pipe_id,
|
| + media::mojom::DecoderBufferPtr buffer) final {
|
| + if (auto* connector = MediaRemotingConnector::GetIfExists(host_))
|
| + connector->SendBufferToRemote(this, pipe_id, std::move(buffer));
|
| + }
|
| +
|
| + private:
|
| + void OnConnectionError() {
|
| + if (auto* connector = MediaRemotingConnector::GetIfExists(host_))
|
| + connector->DeregisterFrameRemoter(this);
|
| + }
|
| +
|
| + RenderFrameHost* const host_;
|
| + const mojo::StrongBinding<media::mojom::Remoter> binding_;
|
| +
|
| + media::mojom::RemoterClientPtr client_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(FrameMediaRemoter);
|
| +};
|
| +
|
| +// static
|
| +MediaRemotingConnector* MediaRemotingConnector::Get(WebContents* contents) {
|
| + MediaRemotingConnector* connector = FromWebContents(contents);
|
| + if (connector)
|
| + return connector;
|
| + connector = new MediaRemotingConnector(contents);
|
| + // The following transfers ownership of |connector| to WebContents.
|
| + contents->SetUserData(UserDataKey(), connector);
|
| + return connector;
|
| +}
|
| +
|
| +// static
|
| +MediaRemotingConnector* MediaRemotingConnector::GetIfExists(
|
| + RenderFrameHost* render_frame_host) {
|
| + if (auto* contents = WebContents::FromRenderFrameHost(render_frame_host))
|
| + return FromWebContents(contents);
|
| + return nullptr;
|
| +}
|
| +
|
| +// static
|
| +void MediaRemotingConnector::CreateRemoter(
|
| + RenderFrameHost* render_frame_host,
|
| + mojo::InterfaceRequest<media::mojom::Remoter> request) {
|
| + // The FrameMediaRemoter instance self-destructs when the bound pipe
|
| + // encounters an error or is closed on the other end.
|
| + new FrameMediaRemoter(render_frame_host, std::move(request));
|
| +}
|
| +
|
| +MediaRemotingConnector::MediaRemotingConnector(WebContents* contents)
|
| + : provider_(nullptr), active_remoter_(nullptr) {}
|
| +
|
| +MediaRemotingConnector::~MediaRemotingConnector() {
|
| + if (provider_)
|
| + SetProvider(nullptr);
|
| +}
|
| +
|
| +void MediaRemotingConnector::SetProvider(MediaRemotingProvider* provider) {
|
| + // Disconnect the prior provider.
|
| + if (provider_) {
|
| + for (FrameMediaRemoter* remoter : remoters_) {
|
| + if (auto* client = remoter->client())
|
| + client->OnRemoteServicesGone();
|
| + }
|
| + if (active_remoter_)
|
| + StopMediaServices(active_remoter_, mojo::String(nullptr));
|
| + }
|
| +
|
| + provider_ = provider;
|
| +
|
| + // Notify the RemoterClients that a new provider of remoting services is
|
| + // available and ready.
|
| + if (provider_) {
|
| + auto* const capabilities = provider_->GetRemoteCapabilities();
|
| + DCHECK(capabilities);
|
| + for (FrameMediaRemoter* remoter : remoters_) {
|
| + if (auto* client = remoter->client())
|
| + client->OnRemoteServicesAvailable(capabilities->Clone());
|
| + }
|
| + }
|
| +}
|
| +
|
| +void MediaRemotingConnector::RegisterFrameRemoter(FrameMediaRemoter* remoter) {
|
| + DCHECK(remoters_.find(remoter) == remoters_.end());
|
| + DCHECK(remoter->client());
|
| + remoters_.insert(remoter);
|
| + if (provider_) {
|
| + auto* const capabilities = provider_->GetRemoteCapabilities();
|
| + DCHECK(capabilities);
|
| + remoter->client()->OnRemoteServicesAvailable(capabilities->Clone());
|
| + }
|
| +}
|
| +
|
| +void MediaRemotingConnector::DeregisterFrameRemoter(
|
| + FrameMediaRemoter* remoter) {
|
| + if (auto* client = remoter->client())
|
| + client->OnRemoteServicesGone();
|
| + if (remoter == active_remoter_)
|
| + StopMediaServices(remoter, mojo::String(nullptr));
|
| + remoters_.erase(remoter);
|
| +}
|
| +
|
| +void MediaRemotingConnector::StartMediaServices(
|
| + FrameMediaRemoter* remoter,
|
| + mojo::ScopedDataPipeConsumerHandle audio_pipe,
|
| + mojo::ScopedDataPipeConsumerHandle video_pipe,
|
| + const base::Callback<void(bool, uint32_t, uint32_t)>& callback) {
|
| + DCHECK(remoters_.find(remoter) != remoters_.end());
|
| + DCHECK(remoter->client());
|
| + const uint32_t audio_pipe_id = audio_pipe->value();
|
| + const uint32_t video_pipe_id = video_pipe->value();
|
| + if (!active_remoter_ && provider_ &&
|
| + provider_->StartMediaServices(
|
| + std::move(audio_pipe), std::move(video_pipe),
|
| + base::Bind(&FrameMediaRemoter::OnMessageFromRemote,
|
| + base::Unretained(remoter)))) {
|
| + active_remoter_ = remoter;
|
| + DCHECK_NE(audio_pipe_id, video_pipe_id);
|
| + callback.Run(true, audio_pipe_id, video_pipe_id);
|
| + return;
|
| + }
|
| + callback.Run(false, MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID);
|
| +}
|
| +
|
| +void MediaRemotingConnector::StopMediaServices(
|
| + FrameMediaRemoter* remoter, const mojo::String& error_reason) {
|
| + if (active_remoter_ != remoter)
|
| + return;
|
| + if (provider_)
|
| + provider_->StopMediaServices(error_reason);
|
| + active_remoter_ = nullptr;
|
| + if (auto* client = remoter->client())
|
| + client->OnMediaServicesStopped("");
|
| +}
|
| +
|
| +void MediaRemotingConnector::SendMessageToRemote(
|
| + FrameMediaRemoter* remoter, mojo::Array<uint8_t> message) {
|
| + if (active_remoter_ != remoter || !provider_)
|
| + return;
|
| + provider_->SendMessageToRemote(std::move(message));
|
| +}
|
| +
|
| +void MediaRemotingConnector::SendBufferToRemote(
|
| + FrameMediaRemoter* remoter, uint32_t pipe_id,
|
| + media::mojom::DecoderBufferPtr buffer) {
|
| + if (active_remoter_ != remoter || !provider_)
|
| + return;
|
| + provider_->SendBufferToRemote(pipe_id, std::move(buffer));
|
| +}
|
| +
|
| +} // namespace media_router
|
|
|