Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2496)

Unified Diff: chrome/browser/media/cast_remoting_connector.cc

Issue 2951523002: Media Remoting: Add mojo interfaces between browser and extension. (Closed)
Patch Set: Fix compile failure on Android bots. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/media/cast_remoting_connector.cc
diff --git a/chrome/browser/media/cast_remoting_connector.cc b/chrome/browser/media/cast_remoting_connector.cc
index 6b52d3f22a15f3051a635d7f5b322e686f0aea22..c83c905dfa3ce380c39a632fb795ed22800acbb4 100644
--- a/chrome/browser/media/cast_remoting_connector.cc
+++ b/chrome/browser/media/cast_remoting_connector.cc
@@ -10,15 +10,11 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
-#include "chrome/browser/media/cast_remoting_connector_messaging.h"
#include "chrome/browser/media/cast_remoting_sender.h"
#include "chrome/browser/media/router/media_router.h"
#include "chrome/browser/media/router/media_router_factory.h"
-#include "chrome/browser/media/router/route_message_observer.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/common/chrome_features.h"
-#include "chrome/common/media_router/media_source_helper.h"
-#include "chrome/common/media_router/route_message.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -30,8 +26,6 @@ using media::mojom::RemotingSinkCapabilities;
using media::mojom::RemotingStartFailReason;
using media::mojom::RemotingStopReason;
-using Messaging = CastRemotingConnectorMessaging;
-
class CastRemotingConnector::RemotingBridge : public media::mojom::Remoter {
public:
// Constructs a "bridge" to delegate calls between the given |source| and
@@ -112,24 +106,6 @@ class CastRemotingConnector::RemotingBridge : public media::mojom::Remoter {
DISALLOW_COPY_AND_ASSIGN(RemotingBridge);
};
-class CastRemotingConnector::MessageObserver
- : public media_router::RouteMessageObserver {
- public:
- MessageObserver(media_router::MediaRouter* router,
- const media_router::MediaRoute::Id& route_id,
- CastRemotingConnector* connector)
- : RouteMessageObserver(router, route_id), connector_(connector) {}
- ~MessageObserver() final {}
-
- private:
- void OnMessagesReceived(
- const std::vector<media_router::RouteMessage>& messages) final {
- connector_->ProcessMessagesFromRoute(messages);
- }
-
- CastRemotingConnector* const connector_;
-};
-
// static
const void* const CastRemotingConnector::kUserDataKey = &kUserDataKey;
@@ -143,9 +119,7 @@ CastRemotingConnector* CastRemotingConnector::Get(
connector = new CastRemotingConnector(
media_router::MediaRouterFactory::GetApiForBrowserContext(
contents->GetBrowserContext()),
- media_router::MediaSourceForTabContentRemoting(
- SessionTabHelper::IdForTab(contents))
- .id());
+ SessionTabHelper::IdForTab(contents));
contents->SetUserData(kUserDataKey, base::WrapUnique(connector));
}
return connector;
@@ -175,15 +149,19 @@ RemotingSinkCapabilities GetFeatureEnabledCapabilities() {
}
} // namespace
-CastRemotingConnector::CastRemotingConnector(
- media_router::MediaRouter* router,
- const media_router::MediaSource::Id& media_source_id)
- : media_router::MediaRoutesObserver(router),
- media_source_id_(media_source_id),
+CastRemotingConnector::CastRemotingConnector(media_router::MediaRouter* router,
+ int32_t tab_id)
+ : media_router_(router),
+ tab_id_(tab_id),
enabled_features_(GetFeatureEnabledCapabilities()),
- session_counter_(0),
active_bridge_(nullptr),
- weak_factory_(this) {}
+ binding_(this),
+ weak_factory_(this) {
+ if (tab_id_ > 0) {
imcheng 2017/06/22 01:13:27 So it seems this class doesn't do much if tab_id_
xjz 2017/06/23 19:02:40 Changes the condition to (tab_id_ != -1). Currentl
+ VLOG(3) << "Register CastRemotingConnector for tab_id = " << tab_id_;
+ media_router_->RegisterRemotingSource(tab_id_, this);
+ }
+}
CastRemotingConnector::~CastRemotingConnector() {
// Assume nothing about destruction/shutdown sequence of a tab. For example,
@@ -195,6 +173,37 @@ CastRemotingConnector::~CastRemotingConnector() {
notifyee->OnSinkGone();
notifyee->OnCastRemotingConnectorDestroyed();
}
+ if (tab_id_ > 0)
+ media_router_->UnRegisterRemotingSource(tab_id_, this);
+}
+
+void CastRemotingConnector::ConnectToService(
+ media::mojom::MirrorServiceRemotingSourceRequest source_request,
+ media::mojom::MirrorServiceRemoterPtr remoter) {
+ DCHECK(!binding_.is_bound());
+ DCHECK(!remoter_);
+ DCHECK(remoter);
+ VLOG(3) << __func__;
imcheng 2017/06/22 01:13:27 nit: move the VLOG either above or below all DCHEC
xjz 2017/06/23 19:02:40 Done.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ binding_.Bind(std::move(source_request));
+ binding_.set_connection_error_handler(base::Bind(
+ &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this)));
+ remoter_ = std::move(remoter);
+ remoter_.set_connection_error_handler(base::Bind(
+ &CastRemotingConnector::OnMirrorServiceStopped, base::Unretained(this)));
+}
+
+void CastRemotingConnector::OnMirrorServiceStopped() {
+ VLOG(3) << __func__;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (binding_.is_bound())
+ binding_.Close();
+ remoter_.reset();
+
+ for (RemotingBridge* notifyee : bridges_)
+ notifyee->OnSinkGone();
}
void CastRemotingConnector::CreateBridge(media::mojom::RemotingSourcePtr source,
@@ -209,7 +218,8 @@ void CastRemotingConnector::RegisterBridge(RemotingBridge* bridge) {
DCHECK(bridges_.find(bridge) == bridges_.end());
bridges_.insert(bridge);
- if (message_observer_ && !active_bridge_)
+ // TODO(xjz): Pass the receiver's capabilities to the source.
+ if (remoter_ && !active_bridge_)
bridge->OnSinkAvailable(enabled_features_);
}
@@ -224,16 +234,19 @@ void CastRemotingConnector::DeregisterBridge(RemotingBridge* bridge,
}
void CastRemotingConnector::StartRemoting(RemotingBridge* bridge) {
+ VLOG(3) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(bridges_.find(bridge) != bridges_.end());
// Refuse to start if there is no remoting route available, or if remoting is
// already active.
- if (!message_observer_) {
- bridge->OnStartFailed(RemotingStartFailReason::ROUTE_TERMINATED);
+ if (!remoter_) {
+ VLOG(3) << "Remoting start failed: No mirror service connected.";
+ bridge->OnStartFailed(RemotingStartFailReason::SERVICE_NOT_CONNECTED);
return;
}
if (active_bridge_) {
+ VLOG(3) << "Remoting start failed: Cannot start multiple.";
bridge->OnStartFailed(RemotingStartFailReason::CANNOT_START_MULTIPLE);
return;
}
@@ -249,13 +262,29 @@ void CastRemotingConnector::StartRemoting(RemotingBridge* bridge) {
}
active_bridge_ = bridge;
+ remoter_->Start();
+}
- // Send a start message to the Cast Provider.
- ++session_counter_; // New remoting session ID.
- SendMessageToProvider(base::StringPrintf(
- Messaging::kStartRemotingMessageFormat, session_counter_));
+void CastRemotingConnector::OnStarted() {
+ VLOG(3) << __func__;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
- bridge->OnStarted();
+ if (!active_bridge_) {
+ remoter_->Stop(media::mojom::RemotingStopReason::SOURCE_GONE);
+ return;
+ }
+ active_bridge_->OnStarted();
+}
+
+void CastRemotingConnector::OnStartFailed(
+ media::mojom::RemotingStartFailReason reason) {
+ VLOG(3) << __func__ << ": reason = " << reason;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!active_bridge_)
+ return;
+ active_bridge_->OnStartFailed(reason);
+ active_bridge_ = nullptr;
}
void CastRemotingConnector::StartRemotingDataStreams(
@@ -264,11 +293,12 @@ void CastRemotingConnector::StartRemotingDataStreams(
mojo::ScopedDataPipeConsumerHandle video_pipe,
media::mojom::RemotingDataStreamSenderRequest audio_sender_request,
media::mojom::RemotingDataStreamSenderRequest video_sender_request) {
+ VLOG(3) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Refuse to start if there is no remoting route available, or if remoting is
// not active for this |bridge|.
- if (!message_observer_ || active_bridge_ != bridge)
+ if (!remoter_ || active_bridge_ != bridge)
return;
// Also, if neither audio nor video pipe was provided, or if a request for a
// RemotingDataStreamSender was not provided for a data pipe, error-out early.
@@ -286,18 +316,38 @@ void CastRemotingConnector::StartRemotingDataStreams(
pending_audio_sender_request_ = std::move(audio_sender_request);
pending_video_sender_request_ = std::move(video_sender_request);
- // Send a "start streams" message to the Cast Provider. The provider is
- // responsible for creating and setting up a remoting Cast Streaming session
- // that will result in new CastRemotingSender instances being created here in
- // the browser process.
- SendMessageToProvider(base::StringPrintf(
- Messaging::kStartStreamsMessageFormat, session_counter_,
- pending_audio_sender_request_.is_pending() ? 'Y' : 'N',
- pending_video_sender_request_.is_pending() ? 'Y' : 'N'));
+ remoter_->StartDataStreams(pending_audio_sender_request_.is_pending(),
+ pending_video_sender_request_.is_pending());
+}
+
+void CastRemotingConnector::OnDataStreamsStarted(int32_t audio_stream_id,
+ int32_t video_stream_id) {
+ VLOG(3) << __func__ << ": audio_stream_id = " << audio_stream_id
+ << " video_stream_id = " << video_stream_id;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!active_bridge_)
+ return;
+
+ if (pending_audio_sender_request_.is_pending()) {
+ cast::CastRemotingSender::FindAndBind(
+ audio_stream_id, std::move(pending_audio_pipe_),
+ std::move(pending_audio_sender_request_),
+ base::Bind(&CastRemotingConnector::OnDataSendFailed,
+ weak_factory_.GetWeakPtr()));
+ }
+ if (pending_video_sender_request_.is_pending()) {
+ cast::CastRemotingSender::FindAndBind(
+ video_stream_id, std::move(pending_video_pipe_),
+ std::move(pending_video_sender_request_),
+ base::Bind(&CastRemotingConnector::OnDataSendFailed,
+ weak_factory_.GetWeakPtr()));
+ }
}
void CastRemotingConnector::StopRemoting(RemotingBridge* bridge,
RemotingStopReason reason) {
+ VLOG(3) << __func__ << ": reason = " << reason;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (active_bridge_ != bridge)
@@ -320,195 +370,77 @@ void CastRemotingConnector::StopRemoting(RemotingBridge* bridge,
bridge->OnSinkGone();
// Note: At this point, all sources should think the sink is gone.
- SendMessageToProvider(base::StringPrintf(
- Messaging::kStopRemotingMessageFormat, session_counter_));
- // Note: Once the Cast Provider sends back an acknowledgement message, all
- // sources will be notified that the remoting sink is available again.
+ if (remoter_)
+ remoter_->Stop(reason);
bridge->OnStopped(reason);
}
+void CastRemotingConnector::OnStopped(RemotingStopReason reason) {
+ VLOG(3) << __func__ << ": reason = " << reason;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!active_bridge_) {
+ // Notify all the sources that the sink is available again.
+ if (remoter_) {
+ // TODO(xjz): Pass the receiver's capabilities to sources.
+ for (RemotingBridge* notifyee : bridges_) {
+ notifyee->OnSinkAvailable(enabled_features_);
imcheng 2017/06/22 01:13:27 Should we notify the other bridges with OnSinkAvai
xjz 2017/06/23 19:02:40 When |active_bridge_| is not null, it indicates th
+ }
+ }
+ return;
+ }
+ StopRemoting(active_bridge_, reason);
+}
+
void CastRemotingConnector::SendMessageToSink(
RemotingBridge* bridge, const std::vector<uint8_t>& message) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// During an active remoting session, simply pass all binary messages through
// to the sink.
- if (!message_observer_ || active_bridge_ != bridge)
+ if (!remoter_ || active_bridge_ != bridge)
return;
- media_router::MediaRoutesObserver::router()->SendRouteBinaryMessage(
- message_observer_->route_id(),
- base::MakeUnique<std::vector<uint8_t>>(message),
- base::Bind(&CastRemotingConnector::HandleSendMessageResult,
- weak_factory_.GetWeakPtr()));
+ remoter_->SendMessageToSink(message);
}
-void CastRemotingConnector::SendMessageToProvider(const std::string& message) {
+void CastRemotingConnector::OnMessageFromSink(
+ const std::vector<uint8_t>& message) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!message_observer_)
+ // During an active remoting session, simply pass all binary messages through
+ // to the source.
+ if (!active_bridge_)
return;
-
- if (active_bridge_) {
- media_router::MediaRoutesObserver::router()->SendRouteMessage(
- message_observer_->route_id(), message,
- base::Bind(&CastRemotingConnector::HandleSendMessageResult,
- weak_factory_.GetWeakPtr()));
- } else {
- struct Helper {
- static void IgnoreSendMessageResult(bool ignored) {}
- };
- media_router::MediaRoutesObserver::router()->SendRouteMessage(
- message_observer_->route_id(), message,
- base::Bind(&Helper::IgnoreSendMessageResult));
- }
+ active_bridge_->OnMessageFromSink(message);
}
-void CastRemotingConnector::ProcessMessagesFromRoute(
- const std::vector<media_router::RouteMessage>& messages) {
+void CastRemotingConnector::OnSinkAvailable(
+ media::mojom::RemotingSinkCapabilities capabilities) {
+ VLOG(3) << __func__ << ": capabilities = " << capabilities;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Note: If any calls to message parsing functions are added/changed here,
- // please update cast_remoting_connector_fuzzertest.cc as well!
-
- for (const media_router::RouteMessage& message : messages) {
- switch (message.type) {
- case media_router::RouteMessage::TEXT:
- // This is a notification message from the Cast Provider, about the
- // execution state of the media remoting session between Chrome and the
- // remote device.
- DCHECK(message.text);
-
- // If this is a "start streams" acknowledgement message, the
- // CastRemotingSenders should now be available to begin consuming from
- // the data pipes.
- if (active_bridge_ &&
- Messaging::IsMessageForSession(
- *message.text,
- Messaging::kStartedStreamsMessageFormatPartial,
- session_counter_)) {
- if (pending_audio_sender_request_.is_pending()) {
- cast::CastRemotingSender::FindAndBind(
- Messaging::GetStreamIdFromStartedMessage(
- *message.text,
- Messaging::kStartedStreamsMessageAudioIdSpecifier),
- std::move(pending_audio_pipe_),
- std::move(pending_audio_sender_request_),
- base::Bind(&CastRemotingConnector::OnDataSendFailed,
- weak_factory_.GetWeakPtr()));
- }
- if (pending_video_sender_request_.is_pending()) {
- cast::CastRemotingSender::FindAndBind(
- Messaging::GetStreamIdFromStartedMessage(
- *message.text,
- Messaging::kStartedStreamsMessageVideoIdSpecifier),
- std::move(pending_video_pipe_),
- std::move(pending_video_sender_request_),
- base::Bind(&CastRemotingConnector::OnDataSendFailed,
- weak_factory_.GetWeakPtr()));
- }
- break;
- }
-
- // If this is a failure message, call StopRemoting().
- if (active_bridge_ &&
- Messaging::IsMessageForSession(*message.text,
- Messaging::kFailedMessageFormat,
- session_counter_)) {
- StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE);
- break;
- }
-
- // If this is a stop acknowledgement message, indicating that the last
- // session was stopped, notify all sources that the sink is once again
- // available.
- if (Messaging::IsMessageForSession(*message.text,
- Messaging::kStoppedMessageFormat,
- session_counter_)) {
- if (active_bridge_) {
- // Hmm...The Cast Provider was in a state that disagrees with this
- // connector. Attempt to resolve this by shutting everything down to
- // effectively reset to a known state.
- LOG(WARNING) << "BUG: Cast Provider sent 'stopped' message during "
- "an active remoting session.";
- StopRemoting(active_bridge_,
- RemotingStopReason::UNEXPECTED_FAILURE);
- }
- for (RemotingBridge* notifyee : bridges_)
- notifyee->OnSinkAvailable(enabled_features_);
- break;
- }
-
- LOG(WARNING) << "BUG: Unexpected message from Cast Provider: "
- << *message.text;
- break;
-
- case media_router::RouteMessage::BINARY: // This is for the source.
- DCHECK(message.binary);
-
- // All binary messages are passed through to the source during an active
- // remoting session.
- if (active_bridge_)
- active_bridge_->OnMessageFromSink(*message.binary);
- break;
- }
- }
+ // The receiver's capabilities are supposed unchanged during an active
+ // remoting session.
+ if (active_bridge_)
+ return;
+
+ // TODO(xjz): Pass the receiver's capabilities to the sources.
+ for (RemotingBridge* notifyee : bridges_)
+ notifyee->OnSinkAvailable(enabled_features_);
}
-void CastRemotingConnector::HandleSendMessageResult(bool success) {
+void CastRemotingConnector::OnError() {
+ VLOG(3) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // A single message send failure is treated as fatal to an active remoting
- // session.
- if (!success && active_bridge_)
- StopRemoting(active_bridge_, RemotingStopReason::MESSAGE_SEND_FAILED);
+ if (active_bridge_)
+ StopRemoting(active_bridge_, RemotingStopReason::UNEXPECTED_FAILURE);
}
void CastRemotingConnector::OnDataSendFailed() {
+ VLOG(3) << __func__;
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// A single data send failure is treated as fatal to an active remoting
// session.
if (active_bridge_)
StopRemoting(active_bridge_, RemotingStopReason::DATA_SEND_FAILED);
}
-
-void CastRemotingConnector::OnRoutesUpdated(
- const std::vector<media_router::MediaRoute>& routes,
- const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // If a remoting route has already been identified, check that it still
- // exists. Otherwise, shut down messaging and any active remoting, and notify
- // the sources that remoting is no longer available.
- if (message_observer_) {
- for (const media_router::MediaRoute& route : routes) {
- if (message_observer_->route_id() == route.media_route_id())
- return; // Remoting route still exists. Take no further action.
- }
- message_observer_.reset();
- if (active_bridge_)
- StopRemoting(active_bridge_, RemotingStopReason::ROUTE_TERMINATED);
- for (RemotingBridge* notifyee : bridges_)
- notifyee->OnSinkGone();
- }
-
- // There shouldn't be an active RemotingBridge at this point, since there is
- // currently no known remoting route.
- DCHECK(!active_bridge_);
-
- // Scan |routes| for a new remoting route. If one is found, begin processing
- // messages on the route, and notify the sources that remoting is now
- // available.
- for (const media_router::MediaRoute& route : routes) {
- if (route.media_source().id() != media_source_id_)
- continue;
- message_observer_.reset(new MessageObserver(
- media_router::MediaRoutesObserver::router(), route.media_route_id(),
- this));
- // TODO(miu): In the future, scan the route ID for sink capabilities
- // properties and pass these to the source in the OnSinkAvailable()
- // notification.
- for (RemotingBridge* notifyee : bridges_)
- notifyee->OnSinkAvailable(enabled_features_);
- break;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698