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

Unified Diff: chrome/browser/media/router/presentation_service_delegate_impl.cc

Issue 1314413005: [Presentation API] 1-UA presentation support + presenter APIs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase again to pick up Yuri's cl Created 5 years, 2 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/router/presentation_service_delegate_impl.cc
diff --git a/chrome/browser/media/router/presentation_service_delegate_impl.cc b/chrome/browser/media/router/presentation_service_delegate_impl.cc
index d32be6e12d075994bf16c4fcc3e6b6e41704e9c8..d221c6ae1b7b78f0714fa6405169daf9b763bba9 100644
--- a/chrome/browser/media/router/presentation_service_delegate_impl.cc
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -9,7 +9,6 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/containers/scoped_ptr_map.h"
#include "base/containers/small_map.h"
-#include "base/guid.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/media/router/create_presentation_session_request.h"
@@ -19,6 +18,8 @@
#include "chrome/browser/media/router/media_router_factory.h"
#include "chrome/browser/media/router/media_sink.h"
#include "chrome/browser/media/router/media_source_helper.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager.h"
+#include "chrome/browser/media/router/offscreen_presentation_manager_factory.h"
#include "chrome/browser/media/router/presentation_media_sinks_observer.h"
#include "chrome/browser/media/router/presentation_session_messages_observer.h"
#include "chrome/browser/media/router/presentation_session_state_observer.h"
@@ -36,6 +37,9 @@ using content::RenderFrameHost;
namespace media_router {
+using OffscreenPresentationSession =
+ OffscreenPresentationManager::OffscreenPresentationSession;
+
namespace {
using DelegateObserver = content::PresentationServiceDelegate::Observer;
@@ -70,7 +74,9 @@ GURL GetLastCommittedURLForFrame(RenderFrameHostId render_frame_host_id) {
// * PresentationFrameManager.RemoveDelegateObserver.
class PresentationFrame {
public:
- PresentationFrame(content::WebContents* web_contents, MediaRouter* router);
+ PresentationFrame(content::WebContents* web_contents,
+ const RenderFrameHostId& render_frame_host_id,
+ MediaRouter* router);
~PresentationFrame();
// Mirror corresponding APIs in PresentationServiceDelegateImpl.
@@ -81,6 +87,9 @@ class PresentationFrame {
bool HasScreenAvailabilityListenerForTest(
const MediaSource::Id& source_id) const;
std::string GetDefaultPresentationId() const;
+ void SendMessage(const content::PresentationSessionInfo& session,
+ scoped_ptr<content::PresentationSessionMessage> message,
+ const content::SendMessageCallback send_message_cb);
bool ListenForSessionStateChange(
content::PresentationSessionStateListener* listener);
void ListenForSessionMessages(
@@ -89,13 +98,12 @@ class PresentationFrame {
void Reset();
const MediaRoute::Id GetRouteId(const std::string& presentation_id) const;
- const std::vector<MediaRoute::Id> GetRouteIds() const;
void OnPresentationSessionClosed(const std::string& presentation_id);
void OnPresentationSessionStarted(
bool is_default_presentation,
const content::PresentationSessionInfo& session,
- const MediaRoute::Id& route_id);
+ const MediaRoute& route);
void OnPresentationServiceDelegateDestroyed() const;
void set_delegate_observer(DelegateObserver* observer) {
@@ -105,30 +113,60 @@ class PresentationFrame {
private:
MediaSource GetMediaSourceFromListener(
content::PresentationScreenAvailabilityListener* listener) const;
+ // Gets the OffscreenPresentationSession associated with |presentation_id|
miu 2015/10/07 21:51:46 nit: add a line of whitespace above this line
imcheng 2015/10/10 04:39:43 Done.
+ // within this frame. Returns nullptr if |presentation_id| is not
+ // registered as an offscreen presentation.
+ OffscreenPresentationSession* FindOffscreenSession(
+ const std::string& presentation_id) const;
+
base::SmallMap<std::map<std::string, MediaRoute::Id>>
presentation_id_to_route_id_;
scoped_ptr<PresentationMediaSinksObserver> sinks_observer_;
+ // Controller objects for offscreen presentations. Note that offscreen
+ // presentations are manipulated with these objects instead of the observers
+ // and MediaRouter objects below.
+ // Maps from presentation ID to the corresponding OffscreenController within
+ // this frame.
+ base::ScopedPtrMap<std::string, scoped_ptr<OffscreenPresentationSession>>
+ offscreen_presentation_sessions_;
+
+ // For non-offscreen presentations.
// Maps from presentation ID to the corresponding presentation session's
// state change observer within this frame.
base::ScopedPtrMap<std::string, scoped_ptr<PresentationSessionStateObserver>>
session_state_observers_;
ScopedVector<PresentationSessionMessagesObserver> session_messages_observers_;
- // References to the owning WebContents, and the corresponding MediaRouter.
- const content::WebContents* web_contents_;
- MediaRouter* router_;
+ // References to the owning WebContents.
+ const content::WebContents* const web_contents_;
+
+ // ID of owning RenderFrameHost.
+ const RenderFrameHostId render_frame_host_id_;
+
+ // References to MediaRouter / OffscreenPresentationManager owned by
+ // the associated BrowserContext. They (and the BrowserContext) are
+ // guaranteed to outlive this object.
+ MediaRouter* const router_;
+ OffscreenPresentationManager* const offscreen_presentation_manager_;
DelegateObserver* delegate_observer_;
};
-PresentationFrame::PresentationFrame(content::WebContents* web_contents,
- MediaRouter* router)
+PresentationFrame::PresentationFrame(
+ content::WebContents* web_contents,
+ const RenderFrameHostId& render_frame_host_id,
+ MediaRouter* router)
: web_contents_(web_contents),
+ render_frame_host_id_(render_frame_host_id),
router_(router),
+ offscreen_presentation_manager_(
+ OffscreenPresentationManagerFactory::GetOrCreateForBrowserContext(
+ web_contents_->GetBrowserContext())),
delegate_observer_(nullptr) {
DCHECK(web_contents_);
DCHECK(router_);
+ DCHECK(offscreen_presentation_manager_);
}
PresentationFrame::~PresentationFrame() {
@@ -142,10 +180,30 @@ void PresentationFrame::OnPresentationServiceDelegateDestroyed() const {
void PresentationFrame::OnPresentationSessionStarted(
bool is_default_presentation,
const content::PresentationSessionInfo& session,
- const MediaRoute::Id& route_id) {
- presentation_id_to_route_id_[session.presentation_id] = route_id;
+ const MediaRoute& route) {
+ const std::string& presentation_id = session.presentation_id;
+ presentation_id_to_route_id_[presentation_id] = route.media_route_id();
if (is_default_presentation && delegate_observer_)
delegate_observer_->OnDefaultPresentationStarted(session);
+ if (route.is_offscreen_presentation()) {
+ DCHECK(!ContainsKey(offscreen_presentation_sessions_, presentation_id));
+ scoped_ptr<OffscreenPresentationSession> offscreen_session =
+ offscreen_presentation_manager_->ConnectToOffscreenPresentation(
+ presentation_id, render_frame_host_id_);
+
+ // If |offscreen_session| is nullptr, then the receiver is most likely
+ // already gone, so the route will die soon. This should happen very rarely
+ // since the receiver has to unregister itself between when offscreen
+ // presentation was created and when the resulting route arrived at MR.
+ if (!offscreen_session) {
+ // TODO(imcheng): we should probably reject the route request in this
+ // case. crbug.com/513859
+ LOG(ERROR) << "CreateOffscreenPresentationConnection returned nullptr.";
miu 2015/10/07 21:51:46 nit: DLOG(ERROR) since this message does not help
imcheng 2015/10/10 04:39:43 Done.
+ } else {
+ offscreen_presentation_sessions_.insert(presentation_id,
+ offscreen_session.Pass());
+ }
+ }
}
void PresentationFrame::OnPresentationSessionClosed(
@@ -163,13 +221,6 @@ const MediaRoute::Id PresentationFrame::GetRouteId(
return it != presentation_id_to_route_id_.end() ? it->second : "";
}
-const std::vector<MediaRoute::Id> PresentationFrame::GetRouteIds() const {
- std::vector<MediaRoute::Id> route_ids;
- for (const auto& e : presentation_id_to_route_id_)
- route_ids.push_back(e.second);
- return route_ids;
-}
-
bool PresentationFrame::SetScreenAvailabilityListener(
content::PresentationScreenAvailabilityListener* listener) {
if (sinks_observer_ && sinks_observer_->listener() == listener)
@@ -208,10 +259,45 @@ void PresentationFrame::Reset() {
presentation_id_to_route_id_.clear();
sinks_observer_.reset();
+ offscreen_presentation_sessions_.clear();
session_state_observers_.clear();
session_messages_observers_.clear();
}
+void PresentationFrame::SendMessage(
+ const content::PresentationSessionInfo& session,
+ scoped_ptr<content::PresentationSessionMessage> message,
+ const content::SendMessageCallback send_message_cb) {
+ auto it = presentation_id_to_route_id_.find(session.presentation_id);
+ if (it == presentation_id_to_route_id_.end()) {
+ DVLOG(2) << "ListenForSessionMessages: no route for "
+ << session.presentation_id;
+ return;
+ }
+
+ OffscreenPresentationSession* offscreen_session =
+ FindOffscreenSession(session.presentation_id);
+ if (offscreen_session) {
+ offscreen_session->SendMessage(message.Pass(), send_message_cb);
+ } else {
+ if (message->is_binary()) {
+ router_->SendRouteBinaryMessage(it->second, message->data.Pass(),
+ send_message_cb);
+ } else {
+ router_->SendRouteMessage(it->second, message->message, send_message_cb);
+ }
+ }
+}
+
+OffscreenPresentationSession* PresentationFrame::FindOffscreenSession(
+ const std::string& presentation_id) const {
+ auto offscreen_session_it =
+ offscreen_presentation_sessions_.find(presentation_id);
+ return offscreen_session_it != offscreen_presentation_sessions_.end()
+ ? offscreen_session_it->second
+ : nullptr;
+}
+
bool PresentationFrame::ListenForSessionStateChange(
content::PresentationSessionStateListener* listener) {
std::string presentation_id(listener->GetSessionInfo().presentation_id);
@@ -221,16 +307,23 @@ bool PresentationFrame::ListenForSessionStateChange(
return false;
}
- if (ContainsKey(session_state_observers_, presentation_id)) {
- DVLOG(2) << "ListenForSessionStateChange: already contains a state "
- << "observer for session " << presentation_id;
- return false;
+ OffscreenPresentationSession* offscreen_session =
+ FindOffscreenSession(presentation_id);
+ if (offscreen_session) {
+ offscreen_session->ListenForStateChanges(listener);
+ return true;
+ } else {
+ if (ContainsKey(session_state_observers_, presentation_id)) {
miu 2015/10/07 21:51:46 OOC, why can there only be one observer? Should |
imcheng 2015/10/10 04:39:43 The only caller is the renderer where Presentation
+ DVLOG(2) << "ListenForSessionStateChange: already contains a state "
+ << "observer for session " << presentation_id;
+ return false;
+ }
+
+ session_state_observers_.insert(
+ presentation_id, make_scoped_ptr(new PresentationSessionStateObserver(
+ listener, it->second, router_)));
+ return true;
}
-
- session_state_observers_.insert(
- presentation_id, make_scoped_ptr(new PresentationSessionStateObserver(
- listener, it->second, router_)));
- return true;
}
void PresentationFrame::ListenForSessionMessages(
@@ -243,8 +336,15 @@ void PresentationFrame::ListenForSessionMessages(
return;
}
- session_messages_observers_.push_back(
- new PresentationSessionMessagesObserver(message_cb, it->second, router_));
+ OffscreenPresentationSession* offscreen_session =
+ FindOffscreenSession(session.presentation_id);
+ if (offscreen_session) {
+ offscreen_session->ListenForMessages(message_cb);
+ } else {
+ session_messages_observers_.push_back(
+ new PresentationSessionMessagesObserver(message_cb, it->second,
+ router_));
+ }
}
MediaSource PresentationFrame::GetMediaSourceFromListener(
@@ -270,6 +370,10 @@ class PresentationFrameManager {
bool RemoveScreenAvailabilityListener(
const RenderFrameHostId& render_frame_host_id,
content::PresentationScreenAvailabilityListener* listener);
+ void SendMessage(const RenderFrameHostId& render_frame_host_id,
+ const content::PresentationSessionInfo& session,
+ scoped_ptr<content::PresentationSessionMessage> message,
+ const content::SendMessageCallback send_message_cb);
bool ListenForSessionStateChange(
const RenderFrameHostId& render_frame_host_id,
content::PresentationSessionStateListener* listener);
@@ -290,15 +394,13 @@ class PresentationFrameManager {
const RenderFrameHostId& render_frame_host_id,
bool is_default_presentation,
const content::PresentationSessionInfo& session,
- const MediaRoute::Id& route_id);
+ const MediaRoute& route);
void OnPresentationSessionClosed(
const RenderFrameHostId& render_frame_host_id,
const std::string& presentation_id);
const MediaRoute::Id GetRouteId(const RenderFrameHostId& render_frame_host_id,
const std::string& presentation_id) const;
- const std::vector<MediaRoute::Id> GetRouteIds(
- const RenderFrameHostId& render_frame_host_id) const;
private:
PresentationFrame* GetOrAddPresentationFrame(
@@ -310,14 +412,14 @@ class PresentationFrameManager {
presentation_frames_;
// References to the owning WebContents, and the corresponding MediaRouter.
+ content::WebContents* const web_contents_;
MediaRouter* router_;
- content::WebContents* web_contents_;
};
PresentationFrameManager::PresentationFrameManager(
content::WebContents* web_contents,
MediaRouter* router)
- : router_(router), web_contents_(web_contents) {
+ : web_contents_(web_contents), router_(router) {
DCHECK(web_contents_);
DCHECK(router_);
}
@@ -331,11 +433,12 @@ void PresentationFrameManager::OnPresentationSessionStarted(
const RenderFrameHostId& render_frame_host_id,
bool is_default_presentation,
const content::PresentationSessionInfo& session,
- const MediaRoute::Id& route_id) {
+ const MediaRoute& route) {
auto presentation_frame = presentation_frames_.get(render_frame_host_id);
- if (presentation_frame)
+ if (presentation_frame) {
presentation_frame->OnPresentationSessionStarted(is_default_presentation,
- session, route_id);
+ session, route);
+ }
}
void PresentationFrameManager::OnPresentationSessionClosed(
@@ -354,13 +457,6 @@ const MediaRoute::Id PresentationFrameManager::GetRouteId(
: "";
}
-const std::vector<MediaRoute::Id> PresentationFrameManager::GetRouteIds(
- const RenderFrameHostId& render_frame_host_id) const {
- auto presentation_frame = presentation_frames_.get(render_frame_host_id);
- return presentation_frame ? presentation_frame->GetRouteIds()
- : std::vector<MediaRoute::Id>();
-}
-
bool PresentationFrameManager::SetScreenAvailabilityListener(
const RenderFrameHostId& render_frame_host_id,
content::PresentationScreenAvailabilityListener* listener) {
@@ -386,6 +482,24 @@ bool PresentationFrameManager::HasScreenAvailabilityListenerForTest(
presentation_frame->HasScreenAvailabilityListenerForTest(source_id);
}
+void PresentationFrameManager::SendMessage(
+ const RenderFrameHostId& render_frame_host_id,
+ const content::PresentationSessionInfo& session,
+ scoped_ptr<content::PresentationSessionMessage> message,
+ const content::SendMessageCallback send_message_cb) {
+ PresentationFrame* presentation_frame =
+ presentation_frames_.get(render_frame_host_id);
+ if (!presentation_frame) {
+ DVLOG(2) << "SendMessage: PresentationFrame does not exist "
+ << "for: (" << render_frame_host_id.first << ", "
+ << render_frame_host_id.second << ")";
+ send_message_cb.Run(false);
+ return;
+ }
+
+ presentation_frame->SendMessage(session, message.Pass(), send_message_cb);
+}
+
bool PresentationFrameManager::ListenForSessionStateChange(
const RenderFrameHostId& render_frame_host_id,
content::PresentationSessionStateListener* listener) {
@@ -437,8 +551,8 @@ PresentationFrame* PresentationFrameManager::GetOrAddPresentationFrame(
if (!presentation_frames_.contains(render_frame_host_id)) {
presentation_frames_.add(
render_frame_host_id,
- scoped_ptr<PresentationFrame>(
- new PresentationFrame(web_contents_, router_)));
+ scoped_ptr<PresentationFrame>(new PresentationFrame(
+ web_contents_, render_frame_host_id, router_)));
}
return presentation_frames_.get(render_frame_host_id);
}
@@ -570,11 +684,12 @@ void PresentationServiceDelegateImpl::OnJoinRouteResponse(
DVLOG(1) << "OnJoinRouteResponse: "
<< "route_id: " << route->media_route_id()
<< ", presentation URL: " << session.presentation_url
- << ", presentation ID: " << session.presentation_id;
+ << ", presentation ID: " << session.presentation_id
+ << ", offscreen? " << route->is_offscreen_presentation();
DCHECK_EQ(session.presentation_id, presentation_id);
- frame_manager_->OnPresentationSessionStarted(
- RenderFrameHostId(render_process_id, render_frame_id), false, session,
- route->media_route_id());
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id);
+ frame_manager_->OnPresentationSessionStarted(rfh_id, false, session,
+ *route);
success_cb.Run(session);
}
}
@@ -584,14 +699,15 @@ void PresentationServiceDelegateImpl::OnStartSessionSucceeded(
int render_frame_id,
const PresentationSessionSuccessCallback& success_cb,
const content::PresentationSessionInfo& new_session,
- const MediaRoute::Id& route_id) {
+ const MediaRoute& route) {
+ const MediaRoute::Id& route_id = route.media_route_id();
DVLOG(1) << "OnStartSessionSucceeded: "
<< "route_id: " << route_id
<< ", presentation URL: " << new_session.presentation_url
<< ", presentation ID: " << new_session.presentation_id;
- frame_manager_->OnPresentationSessionStarted(
- RenderFrameHostId(render_process_id, render_frame_id), false, new_session,
- route_id);
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id);
+ frame_manager_->OnPresentationSessionStarted(rfh_id, false, new_session,
+ route);
success_cb.Run(new_session);
}
@@ -664,9 +780,9 @@ void PresentationServiceDelegateImpl::ListenForSessionMessages(
int render_frame_id,
const content::PresentationSessionInfo& session,
const content::PresentationSessionMessageCallback& message_cb) {
- frame_manager_->ListenForSessionMessages(
- RenderFrameHostId(render_process_id, render_frame_id), session,
- message_cb);
+ RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id);
+ frame_manager_->ListenForSessionMessages(render_frame_host_id, session,
+ message_cb);
}
void PresentationServiceDelegateImpl::SendMessage(
@@ -674,22 +790,10 @@ void PresentationServiceDelegateImpl::SendMessage(
int render_frame_id,
const content::PresentationSessionInfo& session,
scoped_ptr<content::PresentationSessionMessage> message,
- const SendMessageCallback& send_message_cb) {
- const MediaRoute::Id& route_id = frame_manager_->GetRouteId(
- RenderFrameHostId(render_process_id, render_frame_id),
- session.presentation_id);
- if (route_id.empty()) {
- DVLOG(1) << "No active route for " << session.presentation_id;
- send_message_cb.Run(false);
- return;
- }
-
- if (message->is_binary()) {
- router_->SendRouteBinaryMessage(route_id, message->data.Pass(),
- send_message_cb);
- } else {
- router_->SendRouteMessage(route_id, message->message, send_message_cb);
- }
+ const content::SendMessageCallback& send_message_cb) {
+ RenderFrameHostId render_frame_host_id(render_process_id, render_frame_id);
+ frame_manager_->SendMessage(render_frame_host_id, session, message.Pass(),
+ send_message_cb);
}
bool PresentationServiceDelegateImpl::ListenForSessionStateChange(
@@ -700,25 +804,48 @@ bool PresentationServiceDelegateImpl::ListenForSessionStateChange(
RenderFrameHostId(render_process_id, render_frame_id), listener);
}
+void PresentationServiceDelegateImpl::GetPresentationReceiverSession(
+ int render_process_id,
+ int render_frame_id,
+ const content::PresentationReceiverSessionAvailableCallback& callback) {
+ // We only support receiver APIs in offscreen tabs created for offscreen
+ // presentations.
+ // See ReceiverPresentationServiceDelegateImpl for details.
+ NOTIMPLEMENTED();
+ callback.Run(nullptr);
+}
+
+std::vector<content::PresentationSessionInfo>
+PresentationServiceDelegateImpl::GetPresentationReceiverSessions(
+ int render_process_id,
+ int render_frame_id) {
+ // See comment in |GetPresentationReceiverSession()|.
+ NOTIMPLEMENTED();
+ return std::vector<content::PresentationSessionInfo>();
+}
+
void PresentationServiceDelegateImpl::OnRouteResponse(
const MediaRoute* route,
const std::string& presentation_id,
const std::string& error) {
if (!route)
return;
+
const MediaSource& source = route->media_source();
DCHECK(!source.Empty());
if (!default_source_.Equals(source))
return;
+
RenderFrameHost* main_frame = web_contents_->GetMainFrame();
if (!main_frame)
return;
+
RenderFrameHostId render_frame_host_id(GetRenderFrameHostId(main_frame));
- frame_manager_->OnPresentationSessionStarted(
- render_frame_host_id, true,
- content::PresentationSessionInfo(PresentationUrlFromMediaSource(source),
- presentation_id),
- route->media_route_id());
+ content::PresentationSessionInfo session(
+ PresentationUrlFromMediaSource(source), presentation_id);
+
+ frame_manager_->OnPresentationSessionStarted(render_frame_host_id, true,
+ session, *route);
}
void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver(

Powered by Google App Engine
This is Rietveld 408576698