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

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

Issue 1132903002: [MediaRouter] Add implementation of PresentationServiceDelegate (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 7 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
new file mode 100644
index 0000000000000000000000000000000000000000..73ce1e8ab198da9ca09cf54545039f191f96a246
--- /dev/null
+++ b/chrome/browser/media/router/presentation_service_delegate_impl.cc
@@ -0,0 +1,320 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
mark a. foltz 2015/05/11 07:36:21 Copyright
haibinlu 2015/05/13 01:40:19 Done.
+// 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/presentation_service_delegate_impl.h"
+
+#include <string>
+
+#include "base/guid.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/media/router/create_session_request.h"
+#include "chrome/browser/media/router/media_route.h"
+#include "chrome/browser/media/router/media_router.h"
+#include "chrome/browser/media/router/media_router_impl.h"
mark a. foltz 2015/05/11 07:36:21 Why does this class need to know about the MR impl
haibinlu 2015/05/13 01:40:19 removed.
+#include "chrome/browser/media/router/media_router_impl_factory.h"
+#include "chrome/browser/media/router/media_sink.h"
+#include "chrome/browser/media/router/media_source_helper.h"
+#include "chrome/browser/media/router/presentation_helper.h"
+#include "chrome/browser/media/router/presentation_media_sinks_observer.h"
+#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/ui/webui/media_router/media_router_dialog_controller.h"
+#include "content/public/browser/presentation_screen_availability_listener.h"
+#include "content/public/browser/presentation_session.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+
+DEFINE_WEB_CONTENTS_USER_DATA_KEY(
+ media_router::PresentationServiceDelegateImpl);
+
+using content::RenderFrameHost;
+
+namespace media_router {
+
+PresentationServiceDelegateImpl::PresentationServiceDelegateImpl(
+ content::WebContents* web_contents)
+ : num_observers_(0u),
+ web_contents_(web_contents),
+ router_(MediaRouterImplFactory::GetMediaRouterForBrowserContext(
+ web_contents_->GetBrowserContext())),
+ weak_factory_(this) {
+ DCHECK(router_);
+}
+
+PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
+ DCHECK(observers_.empty());
+ DCHECK_EQ(0u, num_observers_);
+
+ for (const auto& delegate_observer_entry : delegate_observers_)
+ delegate_observer_entry.second->OnDelegateDestroyed();
+}
+
+void PresentationServiceDelegateImpl::AddObserver(
+ int render_process_id,
+ int render_frame_id,
+ content::PresentationServiceDelegate::Observer* observer) {
+ DCHECK(observer);
+
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id);
+ DCHECK(!ContainsKey(delegate_observers_, rfh_id));
+
+ delegate_observers_[rfh_id] = observer;
+}
+
+void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id,
+ int render_frame_id) {
+ delegate_observers_.erase(
+ RenderFrameHostId(render_process_id, render_frame_id));
+}
+
+MediaSource PresentationServiceDelegateImpl::GetMediaSourceFromListener(
+ content::PresentationScreenAvailabilityListener* listener) {
+ // If the default presentation URL is empty then fall back to 1-UA mode,
+ // i.e. offscreeen tab rendering.
+ std::string presentation_url(listener->GetPresentationUrl());
+ return presentation_url.empty()
+ ? ForTabMediaSource(SessionTabHelper::IdForTab(web_contents_))
+ : ForPresentationUrl(presentation_url);
+}
+
+bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener(
+ int render_process_id,
+ int routing_id,
+ content::PresentationScreenAvailabilityListener* listener) {
+ DCHECK(listener);
+
+ if (num_observers_ >= kMaxNumSources) {
+ return false;
+ }
+
+ RenderFrameHostId rfh_id(render_process_id, routing_id);
+ MediaSource source(GetMediaSourceFromListener(listener));
+ auto& observers_for_frame = observers_[rfh_id];
+ // Already exists.
+ if (ContainsKey(observers_for_frame, source.id()))
+ return false;
+
+ linked_ptr<PresentationMediaSinksObserver> observer(
+ new PresentationMediaSinksObserver(router_, listener, source));
+ observers_for_frame.insert(std::make_pair(source.id(), observer));
+ num_observers_++;
+ return true;
+}
+
+void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
+ int render_process_id,
+ int routing_id,
+ content::PresentationScreenAvailabilityListener* listener) {
+ DCHECK(listener);
+
+ RenderFrameHostId rfh_id(render_process_id, routing_id);
+ MediaSource source(GetMediaSourceFromListener(listener));
+ auto it = observers_.find(rfh_id);
+ if (it != observers_.end()) {
+ auto& observers_by_id = it->second;
+ auto observer_it = observers_by_id.find(source.id());
+ if (observer_it != observers_by_id.end()) {
+ observers_by_id.erase(observer_it);
+ num_observers_--;
+
+ if (observers_by_id.empty())
+ observers_.erase(it);
+ }
+ }
+}
+
+void PresentationServiceDelegateImpl::Reset(int render_process_id,
+ int routing_id) {
+ RenderFrameHostId rfh_id(render_process_id, routing_id);
+ UnregisterAllObserversFromFrame(rfh_id);
+ default_presentation_infos_.erase(rfh_id);
+ if (IsMainFrame(rfh_id))
+ UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), std::string());
+}
+
+void PresentationServiceDelegateImpl::SetDefaultPresentationUrl(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& default_presentation_url,
+ const std::string& default_presentation_id) {
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id);
+ if (default_presentation_url.empty() && default_presentation_id.empty()) {
+ default_presentation_infos_.erase(rfh_id);
+ } else {
+ default_presentation_infos_[rfh_id].reset(
+ new content::PresentationSessionInfo(default_presentation_url,
+ default_presentation_id));
+ }
+
+ if (IsMainFrame(rfh_id)) {
+ // This is the main frame, that means tab-level default presentation
+ // might have been updated.
+ MediaSource new_default_source;
+ if (!default_presentation_url.empty())
+ new_default_source = ForPresentationUrl(default_presentation_url);
+ std::string new_default_source_host(GetSourceHostForFrame(rfh_id));
+ UpdateDefaultMediaSourceAndNotifyObservers(new_default_source,
+ new_default_source_host);
+ }
+}
+
+bool PresentationServiceDelegateImpl::IsMainFrame(
+ RenderFrameHostId rfh_id) const {
+ RenderFrameHost* main_frame = web_contents_->GetMainFrame();
+ return main_frame && GetRenderFrameHostId(main_frame) == rfh_id;
+}
+
+void PresentationServiceDelegateImpl::
+ UpdateDefaultMediaSourceAndNotifyObservers(
+ const MediaSource& new_default_source,
+ const std::string& new_default_source_host) {
+ if (!new_default_source.Equals(default_source_) ||
+ new_default_source_host != default_source_host_) {
+ default_source_ = new_default_source;
+ default_source_host_ = new_default_source_host;
+ FOR_EACH_OBSERVER(
+ DefaultMediaSourceObserver, default_media_source_observers_,
+ OnDefaultMediaSourceChanged(default_source_, default_source_host_));
+ }
+}
+
+std::string PresentationServiceDelegateImpl::GetOrGeneratePresentationId(
+ RenderFrameHostId rfh_id,
+ const std::string& presentation_id) const {
+ if (!presentation_id.empty())
+ return presentation_id;
+
+ auto it = default_presentation_infos_.find(rfh_id);
+ if (it != default_presentation_infos_.end()) {
+ const std::string& default_presentation_id = it->second->presentation_id;
+ if (!default_presentation_id.empty())
+ return default_presentation_id;
+ }
+
+ return base::GenerateGUID();
+}
+
+void PresentationServiceDelegateImpl::StartSession(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& presentation_url,
+ const std::string& presentation_id,
+ const PresentationSessionSuccessCallback& success_cb,
+ const PresentationSessionErrorCallback& error_cb) {
+ if (presentation_url.empty() || !IsValidPresentationUrl(presentation_url)) {
+ error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN,
+ "Invalid presentation arguments."));
+ return;
+ }
+
+ RenderFrameHostId rfh_id(render_process_id, render_frame_id);
+ scoped_ptr<CreateSessionRequest> context(new CreateSessionRequest(
+ presentation_url, GetOrGeneratePresentationId(rfh_id, presentation_id),
+ GURL(GetSourceHostForFrame(rfh_id)), success_cb, error_cb));
+
+ // NOTE: Currently this request is ignored if a dialog is already open, e.g.
+ // via browser action. In practice, this should rarely happen, but log
+ // an error message in case it does.
+ MediaRouterDialogController* controller =
+ MediaRouterDialogController::GetInstance();
+ DCHECK(controller);
+ bool created = controller->ShowMediaRouterDialogForPresentation(
+ web_contents_, context.Pass());
+ if (!created) {
+ LOG(ERROR) << "Media router dialog already exists. Ignoring StartSession.";
+ error_cb.Run(content::PresentationError(content::PRESENTATION_ERROR_UNKNOWN,
+ "Unable to create dialog."));
+ return;
+ }
+}
+
+void PresentationServiceDelegateImpl::JoinSession(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& presentation_url,
+ const std::string& presentation_id,
+ const PresentationSessionSuccessCallback& success_cb,
+ const PresentationSessionErrorCallback& error_cb) {
+ NOTIMPLEMENTED();
+}
+
+void PresentationServiceDelegateImpl::ListenForSessionMessages(
+ int render_process_id,
+ int render_frame_id,
+ const PresentationSessionMessageCallback& message_cb) {
+ NOTIMPLEMENTED();
+}
+
+void PresentationServiceDelegateImpl::OnRouteCreated(const MediaRoute& route) {
+ const MediaSource& source = route.media_source();
+ DCHECK(!source.Empty());
+ if (default_source_.Equals(source)) {
+ RenderFrameHost* main_frame = web_contents_->GetMainFrame();
+ if (main_frame) {
+ RenderFrameHostId rfh_id(GetRenderFrameHostId(main_frame));
+ auto it = delegate_observers_.find(rfh_id);
+ if (it != delegate_observers_.end()) {
+ // TODO(imcheng): Pass in valid default presentation ID once it is
+ // available from MediaRoute URN.
+ it->second->OnDefaultPresentationStarted(
+ content::PresentationSessionInfo(GetPresentationUrl(source),
+ std::string()));
+ }
+ }
+ }
+}
+
+MediaSource PresentationServiceDelegateImpl::GetDefaultMediaSource() const {
+ return default_source_;
+}
+
+std::string PresentationServiceDelegateImpl::GetSourceHostForFrame(
+ RenderFrameHostId rfh_id) const {
+ RenderFrameHost* rfh = RenderFrameHost::FromID(rfh_id.first, rfh_id.second);
+ DCHECK(rfh);
+ std::string host = rfh->GetLastCommittedURL().host();
+ if (StartsWithASCII(host, "www.", false))
+ host = host.substr(4);
+ return host;
+}
+
+void PresentationServiceDelegateImpl::UnregisterAllObserversFromFrame(
+ RenderFrameHostId rfh_id) {
+ auto it = observers_.find(rfh_id);
+ if (it != observers_.end()) {
+ auto& observers_by_id = it->second;
+ num_observers_ -= observers_by_id.size();
+ observers_.erase(it);
+ }
+}
+
+void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver(
+ DefaultMediaSourceObserver* observer) {
+ default_media_source_observers_.AddObserver(observer);
+}
+
+void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver(
+ DefaultMediaSourceObserver* observer) {
+ default_media_source_observers_.RemoveObserver(observer);
+}
+
+void PresentationServiceDelegateImpl::SetMediaRouterForTest(
+ MediaRouter* router) {
+ router_ = router;
+}
+
+// static
+PresentationServiceDelegateImpl::RenderFrameHostId
+PresentationServiceDelegateImpl::GetRenderFrameHostId(RenderFrameHost* rfh) {
+ int render_process_id = rfh->GetProcess()->GetID();
+ int routing_id = rfh->GetRoutingID();
+ return RenderFrameHostId(render_process_id, routing_id);
+}
+
+base::WeakPtr<PresentationServiceDelegateImpl>
+PresentationServiceDelegateImpl::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+} // namespace media_router

Powered by Google App Engine
This is Rietveld 408576698