| Index: chrome/browser/media/cast_remoting_connector.h
|
| diff --git a/chrome/browser/media/cast_remoting_connector.h b/chrome/browser/media/cast_remoting_connector.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4ced5c22b312bf3aea63c95304fda5d7afa88a3d
|
| --- /dev/null
|
| +++ b/chrome/browser/media/cast_remoting_connector.h
|
| @@ -0,0 +1,199 @@
|
| +// 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.
|
| +
|
| +#ifndef CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_H_
|
| +#define CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_H_
|
| +
|
| +#include <set>
|
| +
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "chrome/browser/media/router/media_routes_observer.h"
|
| +#include "chrome/browser/media/router/route_message.h"
|
| +#include "content/public/browser/web_contents_user_data.h"
|
| +#include "media/mojo/interfaces/remoting.mojom.h"
|
| +
|
| +namespace content {
|
| +class RenderFrameHost;
|
| +}
|
| +
|
| +// CastRemotingConnector connects a single source (a media element in a render
|
| +// frame) with a single sink (a media player in a remote device). There is one
|
| +// instance of a CastRemotingConnector per source WebContents (representing a
|
| +// collection of render frames), and it is created on-demand. The source in the
|
| +// render process represents itself by providing a media::mojom::RemotingSource
|
| +// service instance. The sink is represented by the Media Router Cast Provider.
|
| +//
|
| +// Whenever a RenderFrameHost is created, ChromeContentBrowserClient will call
|
| +// CreateRemoterFactory() to instantiate an implementation of
|
| +// media::mojom::RemoterFactory associated with the connector. This allows one
|
| +// or more media sources in a render frame to create a media::mojom::Remoter to
|
| +// start/stop and execute media remoting. Media sources also provide a
|
| +// media::mojom::RemotingSource so that the connector may notify them when a
|
| +// sink becomes available for remoting and pass binary messages from the sink
|
| +// back to the source.
|
| +//
|
| +// At any time before or after the CastRemotingConnector is created, the
|
| +// Media Router Cast Provider may create a tab remoting media route. This
|
| +// indicates that the provider has found a sink that is capable of remoting and
|
| +// is available for use. At this point, CastRemotingConnector notifies all
|
| +// RemotingSources that a sink is available, and some time later a
|
| +// RemotingSource can request the start of a remoting session. Once the sink is
|
| +// no longer available, the provider terminates the route and
|
| +// CastRemotingConnector notifies all RemotingSources that the sink is gone.
|
| +//
|
| +// Note that only one RemotingSource can remote media at a time. Therefore,
|
| +// CastRemotingConnector must mitigate among simultaneous requests for media
|
| +// remoting, and only allow one at a time. Currently, the policy is "first come,
|
| +// first served."
|
| +//
|
| +// When starting a remoting session, the CastRemotingConnector sends control
|
| +// messages to the Cast Provider. Among its other duties, the provider must then
|
| +// set up a Cast Streaming session to provide a bitstream transport for the
|
| +// media. Once this is done, the provider sends a control message back to
|
| +// CastRemotingConnector to acknowledge this. Then, CastRemotingConnector knows
|
| +// it can look-up and pass the mojo data pipe handles to CastRemotingSenders,
|
| +// and the remoting session will be fully active. The CastRemotingConnector is
|
| +// responsible for passing small binary messages between the source and sink,
|
| +// while the CastRemotingSender handles the high-volume media data transfer.
|
| +class CastRemotingConnector
|
| + : protected content::WebContentsUserData<CastRemotingConnector>,
|
| + public media_router::MediaRoutesObserver {
|
| + public:
|
| + // Returns the instance of the CastRemotingConnector associated with
|
| + // |source_contents|, creating a new instance if needed.
|
| + static CastRemotingConnector* Get(content::WebContents* source_contents);
|
| +
|
| + // Used by ChromeContentBrowserClient to request a binding to a new
|
| + // RemoterFactory for each new render frame. The |render_frame_host| is
|
| + // expected to outlive the mojo message pipe in |request| that the service
|
| + // binds to.
|
| + static void CreateRemoterFactory(content::RenderFrameHost* render_frame_host,
|
| + media::mojom::RemoterFactoryRequest request);
|
| +
|
| + protected:
|
| + friend class content::WebContentsUserData<CastRemotingConnector>;
|
| +
|
| + // Constructor used only by WebContentsUserData.
|
| + explicit CastRemotingConnector(content::WebContents* source_contents);
|
| +
|
| + ~CastRemotingConnector() final;
|
| +
|
| + private:
|
| + // Allow unit tests access to the private constructor and CreateBridge()
|
| + // method, since unit tests don't have a complete browser (i.e., with a
|
| + // WebContents and RenderFrameHost) to work with.
|
| + friend class CastRemotingConnectorTest;
|
| +
|
| + // Implementation of the media::mojom::RemoterFactory, with one instance
|
| + // created per content::RenderFrameHost. An instance of this class is owned by
|
| + // its mojo message pipe.
|
| + class FrameRemoterFactory;
|
| +
|
| + // Implementation of the media::mojom::Remoter service for a single source in
|
| + // a render frame. This is just a "lightweight bridge" that delegates calls
|
| + // back-and-forth between a CastRemotingConnector and a
|
| + // media::mojom::RemotingSource. An instance of this class is owned by its
|
| + // mojo message pipe.
|
| + class RemotingBridge;
|
| +
|
| + // A RouteMessageObserver for the remoting route that passes messages from the
|
| + // Cast Provider back to this connector. An instance of this class only exists
|
| + // while a remoting route is available, and is owned by CastRemotingConnector.
|
| + class MessageObserver;
|
| +
|
| + // Main constructor. |route_source_id| is the remoting route source specific
|
| + // to one tab (WebContents).
|
| + CastRemotingConnector(media_router::MediaRouter* router,
|
| + const media_router::MediaSource::Id& route_source_id);
|
| +
|
| + // Creates a RemotingBridge that implements the requested Remoter service, and
|
| + // binds it to the interface |request|.
|
| + void CreateBridge(media::mojom::RemotingSourcePtr source,
|
| + media::mojom::RemoterRequest request);
|
| +
|
| + // Called by the RemotingBridge constructor/destructor to register/deregister
|
| + // an instance. This allows this connector to broadcast notifications to all
|
| + // active sources.
|
| + void RegisterBridge(RemotingBridge* bridge);
|
| + void DeregisterBridge(RemotingBridge* bridge,
|
| + media::mojom::RemotingStopReason reason);
|
| +
|
| + // These methods are called by RemotingBridge to forward media::mojom::Remoter
|
| + // calls from a source through to this connector. They ensure that only one
|
| + // source is allowed to be in a remoting session at a time, and that no source
|
| + // may interfere with any other.
|
| + void StartRemoting(RemotingBridge* bridge);
|
| + void StartRemotingDataStreams(
|
| + RemotingBridge* bridge,
|
| + mojo::ScopedDataPipeConsumerHandle audio_pipe,
|
| + mojo::ScopedDataPipeConsumerHandle video_pipe,
|
| + media::mojom::RemotingDataStreamSenderRequest audio_sender_request,
|
| + media::mojom::RemotingDataStreamSenderRequest video_sender_request);
|
| + void StopRemoting(RemotingBridge* bridge,
|
| + media::mojom::RemotingStopReason reason);
|
| + void SendMessageToSink(RemotingBridge* bridge,
|
| + const std::vector<uint8_t>& message);
|
| +
|
| + // Send a control message to the Cast Provider. This may or may not succeed,
|
| + // with the success status reported later via HandleSendMessageResult().
|
| + void SendMessageToProvider(const std::string& message);
|
| +
|
| + // Called by the current MessageObserver to process messages observed on the
|
| + // remoting route. There are two types of messages: 1) TEXT control messages
|
| + // from the Cast Provider to set-up and tear-down remoting sessions, and
|
| + // 2) BINARY messages meant to be passed to the active remoting source during
|
| + // a remoting session.
|
| + void ProcessMessagesFromRoute(
|
| + const std::vector<media_router::RouteMessage>& messages);
|
| +
|
| + // Error handlers for message/data sending during an active remoting
|
| + // session. When a failure occurs, these immediately force-stop remoting.
|
| + void HandleSendMessageResult(bool success);
|
| + void OnDataSendFailed();
|
| +
|
| + // MediaRoutesObserver implementation: Scans |routes| to check whether the
|
| + // existing remoting route has gone away and/or there is a new remoting route
|
| + // established, and take the necessary actions to notify sources and/or
|
| + // shutdown an active remoting session.
|
| + void OnRoutesUpdated(
|
| + const std::vector<media_router::MediaRoute>& routes,
|
| + const std::vector<media_router::MediaRoute::Id>& ignored) final;
|
| +
|
| + // Set of registered RemotingBridges, maintained by RegisterBridge() and
|
| + // DeregisterBridge(). These pointers are always valid while they are in this
|
| + // set.
|
| + std::set<RemotingBridge*> bridges_;
|
| +
|
| + // Created when the Media Router Cast Provider has created a media remoting
|
| + // route to a sink that supports remoting and is available for use. This
|
| + // observer simply dispatches messages from the Cast Provider and sink back to
|
| + // this connector. Once the route is gone, this is reset to null.
|
| + std::unique_ptr<MessageObserver> message_observer_;
|
| +
|
| + // Incremented each time StartRemoting() is called, and used as a "current
|
| + // session ID" to ensure that control messaging between this connector and the
|
| + // Cast Provider are referring to the same remoting session. This allows both
|
| + // this connector and the provider to ignore stale messages.
|
| + unsigned int session_counter_;
|
| +
|
| + // When non-null, an active remoting session is taking place, with this
|
| + // pointing to the RemotingBridge being used to communicate with the source.
|
| + RemotingBridge* active_bridge_;
|
| +
|
| + // These temporarily hold the mojo data pipe handles and interface requests
|
| + // until hand-off to the CastRemotingSenders.
|
| + mojo::ScopedDataPipeConsumerHandle pending_audio_pipe_;
|
| + mojo::ScopedDataPipeConsumerHandle pending_video_pipe_;
|
| + media::mojom::RemotingDataStreamSenderRequest pending_audio_sender_request_;
|
| + media::mojom::RemotingDataStreamSenderRequest pending_video_sender_request_;
|
| +
|
| + // Produces weak pointers that are only valid for the current remoting
|
| + // session. This is used to cancel any outstanding callbacks when a remoting
|
| + // session is stopped.
|
| + base::WeakPtrFactory<CastRemotingConnector> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CastRemotingConnector);
|
| +};
|
| +
|
| +#endif // CHROME_BROWSER_MEDIA_CAST_REMOTING_CONNECTOR_H_
|
|
|