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

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

Issue 1055403006: Upstreaming review for Media Router Mojo interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporate latest changes to MR API. 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/media_router_mojo_impl.cc
diff --git a/chrome/browser/media/router/media_router_mojo_impl.cc b/chrome/browser/media/router/media_router_mojo_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..462be53c0a68890239fa3b7ef61242f7455c4718
--- /dev/null
+++ b/chrome/browser/media/router/media_router_mojo_impl.cc
@@ -0,0 +1,384 @@
+// Copyright 2014 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_router_mojo_impl.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/logging.h"
+#include "base/observer_list.h"
+#include "chrome/browser/media/router/media_router_impl.h"
+#include "chrome/browser/media/router/media_router_impl_factory.h"
+#include "chrome/browser/media/router/media_router_mojo_impl_factory.h"
+#include "chrome/browser/media/router/media_router_type_converters.h"
+#include "chrome/browser/media/router/media_routes_observer.h"
+#include "chrome/browser/media/router/media_sinks_observer.h"
+#include "extensions/browser/process_manager.h"
+
+#define DVLOG_WITH_INSTANCE(level) \
+ DVLOG(level) << "MR #" << instance_id_ << ": "
+
+namespace media_router {
+namespace {
+
+void CreateRouteFinished(const MediaSinkId& sink_id,
+ const MediaRouteResponseCallback& callback,
+ interfaces::MediaRoutePtr media_route,
+ const mojo::String& error_text) {
+ if (media_route.is_null()) {
+ // An error occurred.
+ DCHECK(!error_text.is_null());
+ callback.Run(nullptr, (!error_text.get().empty() ? error_text.get()
+ : "Unknown error."));
+ return;
+ }
+ callback.Run(make_scoped_ptr(new MediaRoute(media_route.To<MediaRoute>())),
+ "");
+}
+
+void EventPageWakeComplete(bool success) {
+ if (!success)
+ LOG(ERROR) << "An error encountered while waking the event page.";
+}
+
+} // namespace
+
+MediaRouterMojoImpl::MediaRouterMojoImpl()
+ : event_page_tracker_(nullptr), instance_id_(base::GenerateGUID()) {
+}
+
+MediaRouterMojoImpl::MediaRouterMojoImpl(
+ const std::string& mrpm_extension_id,
+ extensions::EventPageTracker* event_page_tracker_for_test)
+ : MediaRouterMojoImpl() {
+ DCHECK(!mrpm_extension_id.empty());
+ DCHECK(event_page_tracker_for_test);
+ mrpm_extension_id_ = mrpm_extension_id;
+ event_page_tracker_ = event_page_tracker_for_test;
+}
+
+MediaRouterMojoImpl::~MediaRouterMojoImpl() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+// static
+void MediaRouterMojoImpl::BindToRequest(
+ const std::string& extension_id,
+ content::BrowserContext* context,
+ mojo::InterfaceRequest<interfaces::MediaRouterObserver> request) {
+ MediaRouterMojoImpl* impl =
+ MediaRouterMojoImplFactory::GetApiForBrowserContext(context);
+ DCHECK(impl);
+ impl->Bind(request.Pass());
+ impl->MonitorExtension(extension_id, context);
+}
+
+void MediaRouterMojoImpl::Bind(
+ mojo::InterfaceRequest<interfaces::MediaRouterObserver> request) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ binding_.reset(
+ new mojo::Binding<interfaces::MediaRouterObserver>(this, request.Pass()));
+ binding_->set_error_handler(this);
+}
+
+void MediaRouterMojoImpl::OnConnectionError() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ mrpm_.reset();
+ binding_.reset();
+}
+
+void MediaRouterMojoImpl::ProvideMediaRouter(
+ interfaces::MediaRouterPtr mrpm,
+ const interfaces::MediaRouterObserver::ProvideMediaRouterCallback&
+ callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ mrpm_ = mrpm.Pass();
+ mrpm_.set_error_handler(this);
+ callback.Run(instance_id_);
+ ExecutePendingRequests();
+}
+
+void MediaRouterMojoImpl::OnMessage(const mojo::String& route_id,
+ const mojo::String& message) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ NOTIMPLEMENTED();
+}
+
+void MediaRouterMojoImpl::OnIssue(const interfaces::IssuePtr issue) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ NOTIMPLEMENTED();
+}
+
+void MediaRouterMojoImpl::OnSinksReceived(
+ const mojo::String& media_source,
+ mojo::Array<interfaces::MediaSinkPtr> sinks) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG_WITH_INSTANCE(1) << "OnSinksReceived";
+ std::vector<MediaSink> sinks_converted;
+ sinks_converted.reserve(sinks.size());
+
+ for (size_t i = 0; i < sinks.size(); ++i) {
+ sinks_converted.push_back(sinks[i].To<MediaSink>());
+ }
+
+ auto it = sinks_observers_.find(media_source);
+ if (it == sinks_observers_.end()) {
+ DVLOG_WITH_INSTANCE(1)
+ << "Received sink list without any active observers: " << media_source;
+ } else {
+ FOR_EACH_OBSERVER(MediaSinksObserver, *it->second,
+ OnSinksReceived(sinks_converted));
+ }
+}
+
+void MediaRouterMojoImpl::OnRoutesUpdated(
+ mojo::Array<interfaces::MediaRoutePtr> routes) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DVLOG_WITH_INSTANCE(1) << "OnRoutesUpdated";
+
+ std::vector<MediaRoute> routes_converted;
+ routes_converted.reserve(routes.size());
+
+ for (size_t i = 0; i < routes.size(); ++i) {
+ routes_converted.push_back(routes[i].To<MediaRoute>());
+ }
+
+ FOR_EACH_OBSERVER(MediaRoutesObserver, routes_observers_,
+ OnRoutesUpdated(routes_converted));
+}
+
+// ----------------------------------------------------------------------------
+// MediaRouter methods.
+
+void MediaRouterMojoImpl::CreateRoute(
+ const MediaSourceId& source_id,
+ const MediaSinkId& sink_id,
+ const MediaRouteResponseCallback& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoCreateRoute,
+ base::Unretained(this), source_id, sink_id, callback));
+}
+
+void MediaRouterMojoImpl::CloseRoute(const MediaRouteId& route_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoCloseRoute,
+ base::Unretained(this), route_id));
+}
+
+void MediaRouterMojoImpl::PostMessage(const MediaRouteId& route_id,
+ const std::string& message) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoPostMessage,
+ base::Unretained(this), route_id, message));
+}
+
+void MediaRouterMojoImpl::ClearIssue(const Issue::IssueId& issue_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoClearIssue,
+ base::Unretained(this), issue_id));
+}
+
+bool MediaRouterMojoImpl::RegisterMediaSinksObserver(
+ MediaSinksObserver* observer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Lazily create an observer list for the media source and add |observer|
+ // to it.
+ const std::string& source_id = observer->source().id();
+ linked_ptr<ObserverList<MediaSinksObserver>> observer_list =
+ sinks_observers_[source_id];
+ if (!observer_list.get()) {
+ observer_list = make_linked_ptr(new ObserverList<MediaSinksObserver>);
+ sinks_observers_[source_id] = observer_list;
+ } else {
+ if (observer_list->HasObserver(observer)) {
+ DLOG(FATAL) << "Redundant RegisterMediaSinksObserver call detected.";
+ return true;
+ }
+ }
+
+ // Turn on sink observation if this is the first time we've started observing
+ // sinks for the media source.
+ if (!observer_list->might_have_observers()) {
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaSinks,
+ base::Unretained(this), source_id));
+ }
+ observer_list->AddObserver(observer);
+
+ return true;
+}
+
+void MediaRouterMojoImpl::UnregisterMediaSinksObserver(
+ MediaSinksObserver* observer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ const std::string& source_id = observer->source().id();
+ const auto observer_list_it = sinks_observers_.find(source_id);
+ if (observer_list_it == sinks_observers_.end() ||
+ !observer_list_it->second->HasObserver(observer)) {
+ return;
+ }
+ observer_list_it->second->RemoveObserver(observer);
+
+ // If we are removing the final observer for the source, then stop
+ // observing sinks.
+ if (!observer_list_it->second->might_have_observers()) {
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStopObservingMediaSinks,
+ base::Unretained(this), source_id));
+ sinks_observers_.erase(observer_list_it);
+ }
+}
+
+bool MediaRouterMojoImpl::RegisterMediaRoutesObserver(
+ MediaRoutesObserver* observer) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!routes_observers_.HasObserver(observer)) {
+ DLOG(FATAL) << "Redundant RegisterMediaRoutesObserver() call detected.";
+ return true;
+ }
+
+ // TODO(kmarshall): add result caching and max limits.
+ if (!routes_observers_.might_have_observers()) {
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaRoutes,
+ base::Unretained(this)));
+ }
+ routes_observers_.AddObserver(observer);
+ return true;
+}
+
+void MediaRouterMojoImpl::UnregisterMediaRoutesObserver(
+ MediaRoutesObserver* observer) {
+ if (!routes_observers_.HasObserver(observer)) {
+ return;
+ }
+ routes_observers_.RemoveObserver(observer);
+ if (!routes_observers_.might_have_observers()) {
+ RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStopObservingMediaRoutes,
+ base::Unretained(this)));
+ }
+}
+
+void MediaRouterMojoImpl::AddIssuesObserver(IssuesObserver* observer) {
+ NOTIMPLEMENTED(); // TODO(kmarshall): To be landed in a separate CL.
+}
+
+void MediaRouterMojoImpl::RemoveIssuesObserver(IssuesObserver* observer) {
+ NOTIMPLEMENTED();
+}
+
+void MediaRouterMojoImpl::DoCreateRoute(
+ const MediaSourceId& source_id,
+ const MediaSinkId& sink_id,
+ const MediaRouteResponseCallback& callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "CreateRoute " << source_id << "=>" << sink_id;
+ mrpm_->CreateRoute(source_id, sink_id,
+ base::Bind(&CreateRouteFinished, sink_id, callback));
+}
+
+void MediaRouterMojoImpl::DoCloseRoute(const MediaRouteId& route_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "CloseRoute " << route_id;
+ mrpm_->CloseRoute(route_id);
+}
+
+void MediaRouterMojoImpl::DoPostMessage(const MediaRouteId& route_id,
+ const std::string& message) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "PostMessage " << route_id;
+ mrpm_->PostMessage(route_id, message);
+}
+
+void MediaRouterMojoImpl::DoClearIssue(const Issue::IssueId& issue_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "ClearIssue " << issue_id;
+ mrpm_->ClearIssue(issue_id);
+}
+
+void MediaRouterMojoImpl::DoStartObservingMediaSinks(
+ const std::string& source_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "StartObservingMediaSinks: " << source_id;
+ mrpm_->StartObservingMediaSinks(source_id);
+}
+
+void MediaRouterMojoImpl::DoStopObservingMediaSinks(
+ const std::string& source_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "StopObservingMediaSinks: " << source_id;
+ mrpm_->StopObservingMediaSinks(source_id);
+}
+
+void MediaRouterMojoImpl::DoStartObservingMediaRoutes() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "StartObservingMediaRoutes";
+ mrpm_->StartObservingMediaRoutes();
+}
+
+void MediaRouterMojoImpl::DoStopObservingMediaRoutes() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DVLOG_WITH_INSTANCE(1) << "StopObservingMediaRoutes";
+ mrpm_->StopObservingMediaRoutes();
+}
+
+void MediaRouterMojoImpl::EnqueueTask(const base::Closure& closure) {
+ DVLOG_WITH_INSTANCE(2) << "EnqueueTask (size=" << pending_requests_.size()
+ << ")";
+ pending_requests_.push_back(closure);
+}
+
+void MediaRouterMojoImpl::MonitorExtension(const std::string& extension_id,
+ content::BrowserContext* context) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!extension_id.empty());
+ DCHECK(context);
+ mrpm_extension_id_ = extension_id;
+ event_page_tracker_ = extensions::ProcessManager::Get(context);
+}
+
+void MediaRouterMojoImpl::RunOrDefer(const base::Closure& request_cb) {
+ DCHECK(event_page_tracker_);
+ if (event_page_tracker_->IsEventPageSuspended(mrpm_extension_id_)) {
+ DVLOG(1) << "Waking event page.";
+ pending_requests_.push_back(request_cb);
+ if (!event_page_tracker_->WakeEventPage(
+ mrpm_extension_id_, base::Bind(&EventPageWakeComplete))) {
+ LOG(ERROR) << "An error encountered while waking the event page.";
+ }
+ mrpm_.reset();
+ } else if (!mrpm_) {
+ DVLOG(1) << "Extension is awake, awaiting MRPM connection.";
+ pending_requests_.push_back(request_cb);
+ } else {
+ request_cb.Run();
+ }
+}
+
+void MediaRouterMojoImpl::ExecutePendingRequests() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(mrpm_);
+ DCHECK(event_page_tracker_);
+ if (event_page_tracker_->IsEventPageSuspended(mrpm_extension_id_)) {
+ DVLOG_WITH_INSTANCE(1)
+ << "ExecutePendingRequests was called while extension is suspended.";
+ return;
+ }
+
+ for (const auto& next_request : pending_requests_) {
+ next_request.Run();
+ }
+ pending_requests_.clear();
+}
+
+} // namespace media_router
« no previous file with comments | « chrome/browser/media/router/media_router_mojo_impl.h ('k') | chrome/browser/media/router/media_router_mojo_impl_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698