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

Side by Side 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 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/presentation_service_delegate_impl.h"
6
7 #include <string>
8
9 #include "base/containers/scoped_ptr_hash_map.h"
10 #include "base/guid.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "chrome/browser/media/router/create_session_request.h"
14 #include "chrome/browser/media/router/media_route.h"
15 #include "chrome/browser/media/router/media_router.h"
16 #include "chrome/browser/media/router/media_sink.h"
17 #include "chrome/browser/media/router/media_source_helper.h"
18 #include "chrome/browser/media/router/presentation_helper.h"
19 #include "chrome/browser/media/router/presentation_media_sinks_observer.h"
20 #include "chrome/browser/sessions/session_tab_helper.h"
21 #include "content/public/browser/presentation_screen_availability_listener.h"
22 #include "content/public/browser/presentation_session.h"
23 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_process_host.h"
25
26 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
27 media_router::PresentationServiceDelegateImpl);
28
29 using content::RenderFrameHost;
30
31 namespace media_router {
32
33 namespace {
34
35 // Helper function to extract ID for a RFH.
36 RenderFrameHostId GetRenderFrameHostId(RenderFrameHost* rfh) {
37 int render_process_id = rfh->GetProcess()->GetID();
38 int render_frame_id = rfh->GetRoutingID();
39 return RenderFrameHostId(render_process_id, render_frame_id);
40 }
41
42 // Gets the host name associated with the frame given by |rfh_id|.
43 std::string GetSourceHostForFrame(RenderFrameHostId rfh_id) {
44 RenderFrameHost* rfh = RenderFrameHost::FromID(rfh_id.first, rfh_id.second);
45 DCHECK(rfh);
46 std::string host = rfh->GetLastCommittedURL().host();
47 if (StartsWithASCII(host, "www.", false))
48 host = host.substr(4);
49 return host;
50 }
51
52 } // namespace
53
54 // Helper class for PresentationServiceDelegateImpl to manage
55 // listeners and default presentation info in a render frame.
56 class PresentationFrame final {
57 public:
58 using DelegateObserver = content::PresentationServiceDelegate::Observer;
59
60 PresentationFrame(content::WebContents* web_contents, MediaRouter* router);
61 ~PresentationFrame();
62
63 // Returns true if listener was added.
64 bool AddScreenAvailabilityListener(
65 content::PresentationScreenAvailabilityListener* listener);
66
67 // Returns true if listener was removed.
68 bool RemoveScreenAvailabilityListener(
69 content::PresentationScreenAvailabilityListener* listener);
70
71 // Returns true if there is a listener for |source_id|.
72 bool HasScreenAvailabilityListenerForTest(
73 const MediaSourceId& source_id) const;
74
75 // Returns the number of screen-availability listeners.
76 int NumScreenAvailabilityListeners() const;
77
78 // Sets the default presentation URL and ID.
79 void SetDefaultPresentationInfo(const std::string& default_presentation_url,
80 const std::string& default_presentation_id);
81
82 // Returns empty string if no default presentation ID is set.
83 std::string GetDefaultPresentationId() const;
84 void set_delegate_observer(DelegateObserver* observer) {
85 delegate_observer_ = observer;
86 }
87 DelegateObserver* delegate_observer() const { return delegate_observer_; }
88
89 void Reset();
90 void OnDelegateDestroyed();
91
92 private:
93 MediaSource GetMediaSourceFromListener(
94 content::PresentationScreenAvailabilityListener* listener);
95
96 scoped_ptr<content::PresentationSessionInfo> default_presentation_info_;
97 base::ScopedPtrHashMap<MediaSourceId, scoped_ptr<MediaSinksObserver>>
98 sink_observers_;
99
100 // Does not own these objects.
101 const content::WebContents* web_contents_;
102 MediaRouter* router_;
103 DelegateObserver* delegate_observer_;
104 };
105
106 PresentationFrame::PresentationFrame(content::WebContents* web_contents,
107 MediaRouter* router)
108 : web_contents_(web_contents),
109 router_(router),
110 delegate_observer_(nullptr) {
111 DCHECK(web_contents_);
112 DCHECK(router_);
113 }
114
115 PresentationFrame::~PresentationFrame() {
116 DCHECK(sink_observers_.empty());
117 }
118
119 bool PresentationFrame::AddScreenAvailabilityListener(
120 content::PresentationScreenAvailabilityListener* listener) {
121 MediaSource source(GetMediaSourceFromListener(listener));
122 if (sink_observers_.contains(source.id()))
123 return false;
124
125 return sink_observers_.add(source.id(),
126 make_scoped_ptr(new PresentationMediaSinksObserver(
127 router_, listener, source))).second;
128 }
129
130 bool PresentationFrame::RemoveScreenAvailabilityListener(
131 content::PresentationScreenAvailabilityListener* listener) {
132 MediaSource source(GetMediaSourceFromListener(listener));
133 return sink_observers_.erase(source.id()) == 1;
134 }
135
136 bool PresentationFrame::HasScreenAvailabilityListenerForTest(
137 const MediaSourceId& source_id) const {
138 return sink_observers_.contains(source_id);
139 }
140
141 int PresentationFrame::NumScreenAvailabilityListeners() const {
142 return sink_observers_.size();
143 }
144
145 void PresentationFrame::Reset() {
146 sink_observers_.clear();
147 default_presentation_info_.reset();
148 }
149
150 void PresentationFrame::OnDelegateDestroyed() {
151 if (delegate_observer_) {
152 delegate_observer_->OnDelegateDestroyed();
153 }
154 }
155
156 void PresentationFrame::SetDefaultPresentationInfo(
157 const std::string& default_presentation_url,
158 const std::string& default_presentation_id) {
159 if (default_presentation_url.empty() && default_presentation_id.empty()) {
160 default_presentation_info_.reset();
161 } else {
162 default_presentation_info_.reset(new content::PresentationSessionInfo(
163 default_presentation_url, default_presentation_id));
164 }
165 }
166
167 std::string PresentationFrame::GetDefaultPresentationId() const {
168 return default_presentation_info_
169 ? default_presentation_info_->presentation_id
170 : "";
171 }
172
173 MediaSource PresentationFrame::GetMediaSourceFromListener(
174 content::PresentationScreenAvailabilityListener* listener) {
175 // If the default presentation URL is empty then fall back to 1-UA mode,
176 // i.e. offscreeen tab rendering.
177 std::string presentation_url(listener->GetPresentationUrl());
178 return presentation_url.empty()
179 ? ForTabMediaSource(SessionTabHelper::IdForTab(web_contents_))
180 : ForPresentationUrl(presentation_url);
181 }
182
183 // Helper class for PresentationServiceDelegateImpl to manage
184 // PresentationFrames.
185 class PresentationFrameMap final {
186 public:
187 using DelegateObserver = content::PresentationServiceDelegate::Observer;
188
189 PresentationFrameMap(content::WebContents* web_contents, MediaRouter* router);
190 ~PresentationFrameMap();
191
192 // Returns true if listener was added.
193 bool AddScreenAvailabilityListener(
194 RenderFrameHostId rfh_id,
195 content::PresentationScreenAvailabilityListener* listener);
196
197 // Returns true if listener was removed.
198 bool RemoveScreenAvailabilityListener(
199 RenderFrameHostId rfh_id,
200 content::PresentationScreenAvailabilityListener* listener);
201
202 // Returns true if there is a listener for |source_id| in the frame.
203 bool HasScreenAvailabilityListenerForTest(
204 RenderFrameHostId rfh_id,
205 const MediaSourceId& source_id) const;
206
207 // Returns the number of screen-availability listeners.
208 int NumScreenAvailabilityListeners() const;
209
210 // Returns the default presentation URL and ID for the frame.
211 void SetDefaultPresentationInfo(RenderFrameHostId rfh_id,
212 const std::string& default_presentation_url,
213 const std::string& default_presentation_id);
214
215 // Returns empty string if no default presentation ID is set in the frame.
216 std::string GetDefaultPresentationId(RenderFrameHostId rfh_id) const;
217
218 void RegisterPresenationFrame(RenderFrameHostId rfh_id,
219 DelegateObserver* observer);
220 void UnregisterPresenationFrame(RenderFrameHostId rfh_id);
221
222 DelegateObserver* GetDelegateObserver(RenderFrameHostId rfh_id) const;
223
224 void Reset(RenderFrameHostId rfh_id);
225 void OnDelegateDestroyed();
226 void SetMediaRouterForTest(MediaRouter* router);
227
228 private:
229 PresentationFrame* GetOrAddFrame(RenderFrameHostId rfh_id);
230
231 // Maps a frame identifier to a PresentationFrame object for frames
232 // that are using presentation API.
233 base::ScopedPtrHashMap<RenderFrameHostId, scoped_ptr<PresentationFrame>>
234 presentation_frames_;
235
236 // Does not own these two objects.
237 MediaRouter* router_;
238 content::WebContents* web_contents_;
239 };
240
241 PresentationFrameMap::PresentationFrameMap(content::WebContents* web_contents,
242 MediaRouter* router)
243 : web_contents_(web_contents), router_(router) {
244 DCHECK(web_contents_);
245 }
246
247 PresentationFrameMap::~PresentationFrameMap() {
248 }
249
250 bool PresentationFrameMap::AddScreenAvailabilityListener(
251 RenderFrameHostId rfh_id,
252 content::PresentationScreenAvailabilityListener* listener) {
253 DCHECK(listener);
254 if (NumScreenAvailabilityListeners() >=
255 PresentationServiceDelegateImpl::kMaxNumSources) {
256 return false;
257 }
258
259 auto presentation_frame = GetOrAddFrame(rfh_id);
260 return presentation_frame->AddScreenAvailabilityListener(listener);
261 }
262
263 bool PresentationFrameMap::RemoveScreenAvailabilityListener(
264 RenderFrameHostId rfh_id,
265 content::PresentationScreenAvailabilityListener* listener) {
266 DCHECK(listener);
267 auto presentation_frame = presentation_frames_.get(rfh_id);
268 return presentation_frame &&
269 presentation_frame->RemoveScreenAvailabilityListener(listener);
270 }
271
272 bool PresentationFrameMap::HasScreenAvailabilityListenerForTest(
273 RenderFrameHostId rfh_id,
274 const MediaSourceId& source_id) const {
275 auto presentation_frame = presentation_frames_.get(rfh_id);
276 return presentation_frame &&
277 presentation_frame->HasScreenAvailabilityListenerForTest(source_id);
278 }
279
280 int PresentationFrameMap::NumScreenAvailabilityListeners() const {
281 int count = 0;
282 for (const auto& pf : presentation_frames_) {
283 count += pf.second->NumScreenAvailabilityListeners();
284 }
285 return count;
286 }
287
288 void PresentationFrameMap::SetDefaultPresentationInfo(
289 RenderFrameHostId rfh_id,
290 const std::string& default_presentation_url,
291 const std::string& default_presentation_id) {
292 auto presentation_frame = GetOrAddFrame(rfh_id);
293 presentation_frame->SetDefaultPresentationInfo(default_presentation_url,
294 default_presentation_id);
295 }
296
297 std::string PresentationFrameMap::GetDefaultPresentationId(
298 RenderFrameHostId rfh_id) const {
299 auto presentation_frame = presentation_frames_.get(rfh_id);
300 return presentation_frame ? presentation_frame->GetDefaultPresentationId()
301 : "";
302 }
303
304 void PresentationFrameMap::RegisterPresenationFrame(
305 RenderFrameHostId rfh_id,
306 content::PresentationServiceDelegate::Observer* observer) {
307 auto presentation_frame = GetOrAddFrame(rfh_id);
308 presentation_frame->set_delegate_observer(observer);
309 }
310
311 void PresentationFrameMap::UnregisterPresenationFrame(
312 RenderFrameHostId rfh_id) {
313 presentation_frames_.erase(rfh_id);
314 }
315
316 PresentationFrameMap::DelegateObserver*
317 PresentationFrameMap::GetDelegateObserver(RenderFrameHostId rfh_id) const {
318 auto presentation_frame = presentation_frames_.get(rfh_id);
319 return presentation_frame ? presentation_frame->delegate_observer() : nullptr;
320 }
321
322 void PresentationFrameMap::Reset(RenderFrameHostId rfh_id) {
323 auto presentation_frame = presentation_frames_.get(rfh_id);
324 if (presentation_frame)
325 presentation_frame->Reset();
326 }
327
328 void PresentationFrameMap::OnDelegateDestroyed() {
329 for (auto& kv : presentation_frames_)
330 kv.second->OnDelegateDestroyed();
331 }
332
333 PresentationFrame* PresentationFrameMap::GetOrAddFrame(
334 RenderFrameHostId rfh_id) {
335 if (!presentation_frames_.contains(rfh_id)) {
336 presentation_frames_.add(
337 rfh_id, scoped_ptr<PresentationFrame>(
338 new PresentationFrame(web_contents_, router_)));
339 }
340 return presentation_frames_.get(rfh_id);
341 }
342
343 void PresentationFrameMap::SetMediaRouterForTest(MediaRouter* router) {
344 router_ = router;
345 }
346
347 // TODO(haibinlu): Get router from MediaRouterMojoImplFactory once it lands.
348 PresentationServiceDelegateImpl::PresentationServiceDelegateImpl(
349 content::WebContents* web_contents)
350 : web_contents_(web_contents),
351 router_(NULL),
352 frame_map_(new PresentationFrameMap(web_contents, nullptr)),
353 weak_factory_(this) {
354 }
355
356 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
357 frame_map_->OnDelegateDestroyed();
358 }
359
360 void PresentationServiceDelegateImpl::AddObserver(
361 int render_process_id,
362 int render_frame_id,
363 content::PresentationServiceDelegate::Observer* observer) {
364 DCHECK(observer);
365 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
366 frame_map_->RegisterPresenationFrame(rfh_id, observer);
imcheng (use chromium acct) 2015/05/19 22:00:46 nit: rfh_id can be inlined
haibinlu 2015/05/19 22:20:52 Done.
367 }
368
369 void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id,
370 int render_frame_id) {
371 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
372 frame_map_->UnregisterPresenationFrame(rfh_id);
imcheng (use chromium acct) 2015/05/19 22:00:46 ditto
haibinlu 2015/05/19 22:20:53 Done.
373 }
374
375 bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener(
376 int render_process_id,
377 int render_frame_id,
378 content::PresentationScreenAvailabilityListener* listener) {
379 DCHECK(listener);
380 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
381 return frame_map_->AddScreenAvailabilityListener(rfh_id, listener);
imcheng (use chromium acct) 2015/05/19 22:00:46 ditto
haibinlu 2015/05/19 22:20:53 Done.
382 }
383
384 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
385 int render_process_id,
386 int render_frame_id,
387 content::PresentationScreenAvailabilityListener* listener) {
388 DCHECK(listener);
389 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
390 frame_map_->RemoveScreenAvailabilityListener(rfh_id, listener);
imcheng (use chromium acct) 2015/05/19 22:00:46 ditto
haibinlu 2015/05/19 22:20:53 Done.
391 }
392
393 void PresentationServiceDelegateImpl::Reset(int render_process_id,
394 int render_frame_id) {
395 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
396 frame_map_->Reset(rfh_id);
397 if (IsMainFrame(rfh_id))
398 UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), std::string());
399 }
400
401 void PresentationServiceDelegateImpl::SetDefaultPresentationUrl(
402 int render_process_id,
403 int render_frame_id,
404 const std::string& default_presentation_url,
405 const std::string& default_presentation_id) {
406 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
407 frame_map_->SetDefaultPresentationInfo(rfh_id, default_presentation_url,
408 default_presentation_id);
409 if (IsMainFrame(rfh_id)) {
410 // This is the main frame, that means tab-level default presentation
411 // might have been updated.
412 MediaSource new_default_source;
413 if (!default_presentation_url.empty())
414 new_default_source = ForPresentationUrl(default_presentation_url);
415 std::string new_default_source_host(GetSourceHostForFrame(rfh_id));
416 UpdateDefaultMediaSourceAndNotifyObservers(new_default_source,
417 new_default_source_host);
418 }
419 }
420
421 bool PresentationServiceDelegateImpl::IsMainFrame(
422 RenderFrameHostId rfh_id) const {
423 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
424 return main_frame && GetRenderFrameHostId(main_frame) == rfh_id;
425 }
426
427 void PresentationServiceDelegateImpl::
428 UpdateDefaultMediaSourceAndNotifyObservers(
429 const MediaSource& new_default_source,
430 const std::string& new_default_source_host) {
431 if (!new_default_source.Equals(default_source_) ||
432 new_default_source_host != default_source_host_) {
433 default_source_ = new_default_source;
434 default_source_host_ = new_default_source_host;
435 FOR_EACH_OBSERVER(
436 DefaultMediaSourceObserver, default_media_source_observers_,
437 OnDefaultMediaSourceChanged(default_source_, default_source_host_));
438 }
439 }
440
441 void PresentationServiceDelegateImpl::StartSession(
442 int render_process_id,
443 int render_frame_id,
444 const std::string& presentation_url,
445 const std::string& presentation_id,
446 const PresentationSessionSuccessCallback& success_cb,
447 const PresentationSessionErrorCallback& error_cb) {
448 NOTIMPLEMENTED();
449 }
450
451 void PresentationServiceDelegateImpl::JoinSession(
452 int render_process_id,
453 int render_frame_id,
454 const std::string& presentation_url,
455 const std::string& presentation_id,
456 const PresentationSessionSuccessCallback& success_cb,
457 const PresentationSessionErrorCallback& error_cb) {
458 NOTIMPLEMENTED();
459 }
460
461 void PresentationServiceDelegateImpl::ListenForSessionMessages(
462 int render_process_id,
463 int render_frame_id,
464 const PresentationSessionMessageCallback& message_cb) {
465 NOTIMPLEMENTED();
466 }
467
468 void PresentationServiceDelegateImpl::SendMessage(
469 int render_process_id,
470 int render_frame_id,
471 scoped_ptr<content::PresentationSessionMessage> message_request,
472 const SendMessageCallback& send_message_cb) {
473 NOTIMPLEMENTED();
474 }
475
476 void PresentationServiceDelegateImpl::OnRouteCreated(const MediaRoute& route) {
477 const MediaSource& source = route.media_source();
478 DCHECK(!source.Empty());
479 if (default_source_.Equals(source)) {
480 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
481 if (main_frame) {
482 RenderFrameHostId rfh_id(GetRenderFrameHostId(main_frame));
483 auto observer = frame_map_->GetDelegateObserver(rfh_id);
484 if (observer) {
485 // TODO(imcheng): Pass in valid default presentation ID once it is
486 // available from MediaRoute URN.
487 observer->OnDefaultPresentationStarted(content::PresentationSessionInfo(
488 GetPresentationUrl(source), std::string()));
489 }
490 }
491 }
492 }
493
494 void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver(
495 DefaultMediaSourceObserver* observer) {
496 default_media_source_observers_.AddObserver(observer);
497 }
498
499 void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver(
500 DefaultMediaSourceObserver* observer) {
501 default_media_source_observers_.RemoveObserver(observer);
502 }
503
504 void PresentationServiceDelegateImpl::SetMediaRouterForTest(
505 MediaRouter* router) {
506 router_ = router;
507 frame_map_->SetMediaRouterForTest(router);
508 }
509
510 base::WeakPtr<PresentationServiceDelegateImpl>
511 PresentationServiceDelegateImpl::GetWeakPtr() {
512 return weak_factory_.GetWeakPtr();
513 }
514
515 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
516 RenderFrameHostId rfh_id,
517 const MediaSourceId& source_id) const {
518 return frame_map_->HasScreenAvailabilityListenerForTest(rfh_id, source_id);
519 }
520
521 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698