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

Side by Side Diff: chrome/browser/media/router/media_router_mojo_impl.cc

Issue 1126923002: Add Media Router Mojo impl code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed duplicate entries from media_router_tests.gypi. 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media/router/media_router_mojo_impl.h"
6
7 #include "base/bind.h"
8 #include "base/guid.h"
9 #include "base/logging.h"
10 #include "base/observer_list.h"
11 #include "chrome/browser/media/router/media_router_impl.h"
12 #include "chrome/browser/media/router/media_router_impl_factory.h"
13 #include "chrome/browser/media/router/media_router_mojo_impl_factory.h"
14 #include "chrome/browser/media/router/media_router_type_converters.h"
15 #include "chrome/browser/media/router/media_routes_observer.h"
16 #include "chrome/browser/media/router/media_sinks_observer.h"
17 #include "extensions/browser/process_manager.h"
18
19 #define DVLOG_WITH_INSTANCE(level) \
20 DVLOG(level) << "MR #" << instance_id_ << ": "
21
22 #define DVLOG_WITH_INSTANCE(level) DLOG(level) << "MR #" << instance_id_ << ": "
23
24 namespace media_router {
25 namespace {
26
27 // Converts the callback result of calling Mojo CreateRoute() into a local
28 // callback.
29 void CreateRouteFinished(const MediaSinkId& sink_id,
30 const MediaRouteResponseCallback& callback,
31 interfaces::MediaRoutePtr media_route,
32 const mojo::String& error_text) {
33 if (media_route.is_null()) {
34 // An error occurred.
35 DCHECK(!error_text.is_null());
36 callback.Run(nullptr, !error_text.get().empty() ? error_text.get()
37 : "Unknown error.");
38 return;
39 }
40 callback.Run(make_scoped_ptr(new MediaRoute(media_route.To<MediaRoute>())),
41 "");
42 }
43
44 void EventPageWakeComplete(bool success) {
45 if (!success)
46 LOG(ERROR) << "An error encountered while waking the event page.";
47 }
48
49 } // namespace
50
51 MediaRouterMojoImpl::MediaRouterMojoImpl()
52 : event_page_tracker_(nullptr), instance_id_(base::GenerateGUID()) {
53 }
54
55 MediaRouterMojoImpl::MediaRouterMojoImpl(
56 const std::string& mrpm_extension_id,
57 extensions::EventPageTracker* event_page_tracker_for_test)
58 : MediaRouterMojoImpl() {
59 DCHECK(!mrpm_extension_id.empty());
60 DCHECK(event_page_tracker_for_test);
61 mrpm_extension_id_ = mrpm_extension_id;
62 event_page_tracker_ = event_page_tracker_for_test;
63 }
64
65 MediaRouterMojoImpl::~MediaRouterMojoImpl() {
66 DCHECK(thread_checker_.CalledOnValidThread());
67 }
68
69 // static
70 void MediaRouterMojoImpl::BindToRequest(
71 const std::string& extension_id,
72 content::BrowserContext* context,
73 mojo::InterfaceRequest<interfaces::MediaRouterObserver> request) {
74 MediaRouterMojoImpl* impl =
75 MediaRouterMojoImplFactory::GetApiForBrowserContext(context);
76 DCHECK(impl);
77 impl->Bind(request.Pass());
78 impl->MonitorExtension(extension_id, context);
79 }
80
81 void MediaRouterMojoImpl::Bind(
82 mojo::InterfaceRequest<interfaces::MediaRouterObserver> request) {
83 DCHECK(thread_checker_.CalledOnValidThread());
84 binding_.reset(
85 new mojo::Binding<interfaces::MediaRouterObserver>(this, request.Pass()));
86 binding_->set_error_handler(this);
87 }
88
89 void MediaRouterMojoImpl::OnConnectionError() {
90 DCHECK(thread_checker_.CalledOnValidThread());
91 mojo_media_router_.reset();
92 binding_.reset();
93 }
94
95 void MediaRouterMojoImpl::ProvideMediaRouter(
96 interfaces::MediaRouterPtr media_router_ptr,
97 const interfaces::MediaRouterObserver::ProvideMediaRouterCallback&
98 callback) {
99 DCHECK(thread_checker_.CalledOnValidThread());
100 mojo_media_router_ = media_router_ptr.Pass();
101 mojo_media_router_.set_error_handler(this);
102 callback.Run(instance_id_);
103 ExecutePendingRequests();
imcheng (use chromium acct) 2015/05/14 21:30:13 Consider inlining this since there's only 1 caller
Kevin M 2015/05/14 22:46:35 I added an "inline" keyword. I think that organizi
104 }
105
106 void MediaRouterMojoImpl::OnMessage(const mojo::String& route_id,
107 const mojo::String& message) {
108 DCHECK(thread_checker_.CalledOnValidThread());
109 NOTIMPLEMENTED();
110 }
111
112 void MediaRouterMojoImpl::OnIssue(const interfaces::IssuePtr issue) {
113 DCHECK(thread_checker_.CalledOnValidThread());
114 NOTIMPLEMENTED();
115 }
116
117 void MediaRouterMojoImpl::OnSinksReceived(
118 const mojo::String& media_source,
119 mojo::Array<interfaces::MediaSinkPtr> sinks) {
120 DCHECK(thread_checker_.CalledOnValidThread());
121 DVLOG_WITH_INSTANCE(1) << "OnSinksReceived";
122 std::vector<MediaSink> sinks_converted;
123 sinks_converted.reserve(sinks.size());
124
125 for (size_t i = 0; i < sinks.size(); ++i) {
126 sinks_converted.push_back(sinks[i].To<MediaSink>());
127 }
128
129 auto it = sinks_observers_.find(media_source);
130 if (it == sinks_observers_.end()) {
131 DVLOG_WITH_INSTANCE(1)
132 << "Received sink list without any active observers: " << media_source;
133 } else {
134 FOR_EACH_OBSERVER(MediaSinksObserver, *it->second,
135 OnSinksReceived(sinks_converted));
136 }
137 }
138
139 void MediaRouterMojoImpl::OnRoutesUpdated(
140 mojo::Array<interfaces::MediaRoutePtr> routes) {
141 DCHECK(thread_checker_.CalledOnValidThread());
142 DVLOG_WITH_INSTANCE(1) << "OnRoutesUpdated";
143
144 std::vector<MediaRoute> routes_converted;
145 routes_converted.reserve(routes.size());
146
147 for (size_t i = 0; i < routes.size(); ++i) {
148 routes_converted.push_back(routes[i].To<MediaRoute>());
149 }
150
151 FOR_EACH_OBSERVER(MediaRoutesObserver, routes_observers_,
152 OnRoutesUpdated(routes_converted));
153 }
154
155 // ----------------------------------------------------------------------------
156 // MediaRouter methods.
157
158 void MediaRouterMojoImpl::CreateRoute(
159 const MediaSourceId& source_id,
160 const MediaSinkId& sink_id,
161 const MediaRouteResponseCallback& callback) {
162 DCHECK(thread_checker_.CalledOnValidThread());
163 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoCreateRoute,
164 base::Unretained(this), source_id, sink_id, callback));
165 }
166
167 void MediaRouterMojoImpl::CloseRoute(const MediaRouteId& route_id) {
168 DCHECK(thread_checker_.CalledOnValidThread());
169 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoCloseRoute,
170 base::Unretained(this), route_id));
171 }
172
173 void MediaRouterMojoImpl::PostMessage(const MediaRouteId& route_id,
174 const std::string& message) {
175 DCHECK(thread_checker_.CalledOnValidThread());
176 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoPostMessage,
177 base::Unretained(this), route_id, message));
178 }
179
180 void MediaRouterMojoImpl::ClearIssue(const Issue::IssueId& issue_id) {
181 DCHECK(thread_checker_.CalledOnValidThread());
182 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoClearIssue,
183 base::Unretained(this), issue_id));
184 }
185
186 bool MediaRouterMojoImpl::RegisterMediaSinksObserver(
187 MediaSinksObserver* observer) {
188 DCHECK(thread_checker_.CalledOnValidThread());
189
190 // Create an observer list for the media source and add |observer|
191 // to it. Fail if |observer| is already registered.
192 const std::string& source_id = observer->source().id();
193 linked_ptr<ObserverList<MediaSinksObserver>> observer_list =
194 sinks_observers_[source_id];
195 if (!observer_list.get()) {
196 observer_list = make_linked_ptr(new ObserverList<MediaSinksObserver>);
197 sinks_observers_[source_id] = observer_list;
198 } else {
199 if (observer_list->HasObserver(observer)) {
200 DLOG_WITH_INSTANCE(FATAL)
201 << "Redundant RegisterMediaSinksObserver call detected.";
202 return true;
imcheng (use chromium acct) 2015/05/14 21:30:13 return false instead?
Kevin M 2015/05/14 22:46:35 Done
203 }
204 }
205
206 // Turn on sink observation if this is the first time we've started observing
207 // sinks for the media source.
208 if (!observer_list->might_have_observers()) {
imcheng (use chromium acct) 2015/05/14 21:30:13 Because we don't have caching anymore, we should a
Kevin M 2015/05/14 22:46:35 Done.
209 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaSinks,
210 base::Unretained(this), source_id));
211 }
212 observer_list->AddObserver(observer);
213
214 return true;
215 }
216
217 void MediaRouterMojoImpl::UnregisterMediaSinksObserver(
218 MediaSinksObserver* observer) {
219 DCHECK(thread_checker_.CalledOnValidThread());
220
221 const std::string& source_id = observer->source().id();
222 const auto observer_list_it = sinks_observers_.find(source_id);
223 if (observer_list_it == sinks_observers_.end() ||
224 !observer_list_it->second->HasObserver(observer)) {
225 return;
226 }
227 observer_list_it->second->RemoveObserver(observer);
228
229 // If we are removing the final observer for the source, then stop
230 // observing sinks for it.
231 if (!observer_list_it->second->might_have_observers()) {
232 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStopObservingMediaSinks,
233 base::Unretained(this), source_id));
234 sinks_observers_.erase(observer_list_it);
235 }
236 }
237
238 bool MediaRouterMojoImpl::RegisterMediaRoutesObserver(
239 MediaRoutesObserver* observer) {
240 DCHECK(thread_checker_.CalledOnValidThread());
241 if (routes_observers_.HasObserver(observer)) {
242 DLOG(FATAL) << "Redundant RegisterMediaRoutesObserver() call detected.";
243 return true;
244 }
245
246 // TODO(kmarshall): add result caching and max limits.
imcheng (use chromium acct) 2015/05/14 21:30:13 ditto on caching
Kevin M 2015/05/14 22:46:35 Done.
247 if (!routes_observers_.might_have_observers()) {
248 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStartObservingMediaRoutes,
249 base::Unretained(this)));
250 }
251 routes_observers_.AddObserver(observer);
252 return true;
253 }
254
255 void MediaRouterMojoImpl::UnregisterMediaRoutesObserver(
256 MediaRoutesObserver* observer) {
257 if (!routes_observers_.HasObserver(observer)) {
imcheng (use chromium acct) 2015/05/14 21:30:13 curly brace not needed for a single line
Kevin M 2015/05/14 22:46:35 Done.
258 return;
259 }
260 routes_observers_.RemoveObserver(observer);
261 if (!routes_observers_.might_have_observers()) {
262 RunOrDefer(base::Bind(&MediaRouterMojoImpl::DoStopObservingMediaRoutes,
263 base::Unretained(this)));
264 }
265 }
266
267 void MediaRouterMojoImpl::AddIssuesObserver(IssuesObserver* observer) {
268 NOTIMPLEMENTED();
269 }
270
271 void MediaRouterMojoImpl::RemoveIssuesObserver(IssuesObserver* observer) {
272 NOTIMPLEMENTED();
273 }
274
275 void MediaRouterMojoImpl::DoCreateRoute(
276 const MediaSourceId& source_id,
277 const MediaSinkId& sink_id,
278 const MediaRouteResponseCallback& callback) {
279 DCHECK(thread_checker_.CalledOnValidThread());
280 DCHECK(mojo_media_router_);
281 DVLOG_WITH_INSTANCE(1) << "CreateRoute " << source_id << "=>" << sink_id;
282 mojo_media_router_->CreateRoute(
283 source_id, sink_id, base::Bind(&CreateRouteFinished, sink_id, callback));
284 }
285
286 void MediaRouterMojoImpl::DoCloseRoute(const MediaRouteId& route_id) {
287 DCHECK(thread_checker_.CalledOnValidThread());
288 DCHECK(mojo_media_router_);
289 DVLOG_WITH_INSTANCE(1) << "CloseRoute " << route_id;
290 mojo_media_router_->CloseRoute(route_id);
291 }
292
293 void MediaRouterMojoImpl::DoPostMessage(const MediaRouteId& route_id,
294 const std::string& message) {
295 DCHECK(thread_checker_.CalledOnValidThread());
296 DCHECK(mojo_media_router_);
297 DVLOG_WITH_INSTANCE(1) << "PostMessage " << route_id;
298 mojo_media_router_->PostMessage(route_id, message);
299 }
300
301 void MediaRouterMojoImpl::DoClearIssue(const Issue::IssueId& issue_id) {
302 DCHECK(thread_checker_.CalledOnValidThread());
303 DCHECK(mojo_media_router_);
304 DVLOG_WITH_INSTANCE(1) << "ClearIssue " << issue_id;
305 mojo_media_router_->ClearIssue(issue_id);
306 }
307
308 void MediaRouterMojoImpl::DoStartObservingMediaSinks(
309 const std::string& source_id) {
310 DCHECK(thread_checker_.CalledOnValidThread());
311 DCHECK(mojo_media_router_);
312 DVLOG_WITH_INSTANCE(1) << "StartObservingMediaSinks: " << source_id;
313 mojo_media_router_->StartObservingMediaSinks(source_id);
314 }
315
316 void MediaRouterMojoImpl::DoStopObservingMediaSinks(
317 const std::string& source_id) {
318 DCHECK(thread_checker_.CalledOnValidThread());
319 DCHECK(mojo_media_router_);
320 DVLOG_WITH_INSTANCE(1) << "StopObservingMediaSinks: " << source_id;
321 mojo_media_router_->StopObservingMediaSinks(source_id);
322 }
323
324 void MediaRouterMojoImpl::DoStartObservingMediaRoutes() {
325 DCHECK(thread_checker_.CalledOnValidThread());
326 DCHECK(mojo_media_router_);
327 DVLOG_WITH_INSTANCE(1) << "StartObservingMediaRoutes";
328 mojo_media_router_->StartObservingMediaRoutes();
329 }
330
331 void MediaRouterMojoImpl::DoStopObservingMediaRoutes() {
332 DCHECK(thread_checker_.CalledOnValidThread());
333 DCHECK(mojo_media_router_);
334 DVLOG_WITH_INSTANCE(1) << "StopObservingMediaRoutes";
335 mojo_media_router_->StopObservingMediaRoutes();
336 }
337
338 void MediaRouterMojoImpl::EnqueueTask(const base::Closure& closure) {
339 DVLOG_WITH_INSTANCE(2) << "EnqueueTask (size=" << pending_requests_.size()
340 << ")";
341 pending_requests_.push_back(closure);
342 }
343
344 void MediaRouterMojoImpl::MonitorExtension(const std::string& extension_id,
345 content::BrowserContext* context) {
346 DCHECK(thread_checker_.CalledOnValidThread());
347 DCHECK(context);
348 mrpm_extension_id_ = extension_id;
349 event_page_tracker_ = extensions::ProcessManager::Get(context);
350 }
351
352 void MediaRouterMojoImpl::RunOrDefer(const base::Closure& request_cb) {
353 DCHECK(event_page_tracker_);
354 if (event_page_tracker_->IsEventPageSuspended(mrpm_extension_id_)) {
355 DVLOG_WITH_INSTANCE(1) << "Waking event page.";
356 pending_requests_.push_back(request_cb);
357 if (!event_page_tracker_->WakeEventPage(
358 mrpm_extension_id_, base::Bind(&EventPageWakeComplete))) {
359 LOG(ERROR) << "An error encountered while waking the event page.";
360 }
361 mojo_media_router_.reset();
362 } else if (!mojo_media_router_) {
363 DVLOG_WITH_INSTANCE(1) << "Extension is awake, awaiting MRPM connection.";
364 pending_requests_.push_back(request_cb);
365 } else {
366 request_cb.Run();
imcheng (use chromium acct) 2015/05/14 21:30:13 I wonder if we can add a DCHECK(mojo_media_router_
Kevin M 2015/05/14 22:46:35 No need to have a DCHECK on mojo_media_router_ bec
367 }
368 }
369
370 void MediaRouterMojoImpl::ExecutePendingRequests() {
371 DCHECK(thread_checker_.CalledOnValidThread());
372 DCHECK(mojo_media_router_);
373 DCHECK(event_page_tracker_);
374 if (event_page_tracker_->IsEventPageSuspended(mrpm_extension_id_)) {
imcheng (use chromium acct) 2015/05/14 21:30:13 In what conditions will that happen? Should it be
Kevin M 2015/05/14 22:46:35 If the extension shuts down immediately after Prov
375 DVLOG_WITH_INSTANCE(1)
376 << "ExecutePendingRequests was called while extension is suspended.";
377 return;
378 }
379
380 for (const auto& next_request : pending_requests_) {
imcheng (use chromium acct) 2015/05/14 21:30:13 curly braces not needed
Kevin M 2015/05/14 22:46:35 Done.
381 next_request.Run();
382 }
383 pending_requests_.clear();
384 }
385
386 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698