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

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: Addresses Derek's comments 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 explicit PresentationFrame(content::WebContents* web_contents,
imcheng (use chromium acct) 2015/05/19 20:03:29 rm explicit
haibinlu 2015/05/19 21:14:35 Done.
61 MediaRouter* router);
62 ~PresentationFrame();
63
64 // Returns true if listener was added.
65 bool AddScreenAvailabilityListener(
66 content::PresentationScreenAvailabilityListener* listener);
67
68 // Returns true if listener was removed.
69 bool RemoveScreenAvailabilityListener(
70 content::PresentationScreenAvailabilityListener* listener);
71
72 // Returns true if there is a listener for |source_id|.
73 bool HasScreenAvailabilityListenerForTest(
74 const MediaSourceId& source_id) const;
75
76 // Returns the number of screen-availability listeners.
77 int NumScreenAvailabilityListeners() const;
78
79 // Sets the default presentation URL and ID.
80 void SetDefaultPresentationInfo(const std::string& default_presentation_url,
81 const std::string& default_presentation_id);
82
83 // Returns empty string if no default presentation ID is set.
84 std::string GetDefaultPresentationId() const;
85 void set_delegate_observer(DelegateObserver* observer) {
86 delegate_observer_ = observer;
87 }
88 DelegateObserver* delegate_observer() const { return delegate_observer_; }
89
90 void Reset();
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 Reset();
imcheng (use chromium acct) 2015/05/19 20:03:29 Why does Reset() need to be called? The dtor will
haibinlu 2015/05/19 21:14:35 removed
118 if (delegate_observer_) {
119 delegate_observer_->OnDelegateDestroyed();
imcheng (use chromium acct) 2015/05/19 20:03:29 OnDelegateDestroyed() should be called in Presesen
haibinlu 2015/05/19 21:14:35 Done.
120 }
121 }
122
123 bool PresentationFrame::AddScreenAvailabilityListener(
124 content::PresentationScreenAvailabilityListener* listener) {
125 MediaSource source(GetMediaSourceFromListener(listener));
126 if (sink_observers_.contains(source.id()))
127 return false;
128
129 return sink_observers_.add(source.id(),
130 make_scoped_ptr(new PresentationMediaSinksObserver(
131 router_, listener, source))).second;
132 }
133
134 bool PresentationFrame::RemoveScreenAvailabilityListener(
135 content::PresentationScreenAvailabilityListener* listener) {
136 MediaSource source(GetMediaSourceFromListener(listener));
137 return sink_observers_.erase(source.id()) == 1;
138 }
139
140 bool PresentationFrame::HasScreenAvailabilityListenerForTest(
141 const MediaSourceId& source_id) const {
142 return sink_observers_.contains(source_id);
143 }
144
145 int PresentationFrame::NumScreenAvailabilityListeners() const {
146 return sink_observers_.size();
147 }
148
149 void PresentationFrame::Reset() {
150 sink_observers_.clear();
151 default_presentation_info_.reset();
152 }
153
154 void PresentationFrame::SetDefaultPresentationInfo(
155 const std::string& default_presentation_url,
156 const std::string& default_presentation_id) {
157 if (default_presentation_url.empty() && default_presentation_id.empty()) {
158 default_presentation_info_.reset();
159 } else {
160 default_presentation_info_.reset(new content::PresentationSessionInfo(
161 default_presentation_url, default_presentation_id));
162 }
163 }
164
165 std::string PresentationFrame::GetDefaultPresentationId() const {
166 return default_presentation_info_
167 ? default_presentation_info_->presentation_id
168 : "";
169 }
170
171 MediaSource PresentationFrame::GetMediaSourceFromListener(
172 content::PresentationScreenAvailabilityListener* listener) {
173 // If the default presentation URL is empty then fall back to 1-UA mode,
174 // i.e. offscreeen tab rendering.
175 std::string presentation_url(listener->GetPresentationUrl());
176 return presentation_url.empty()
177 ? ForTabMediaSource(SessionTabHelper::IdForTab(web_contents_))
178 : ForPresentationUrl(presentation_url);
179 }
180
181 // Helper class for PresentationServiceDelegateImpl to manage
182 // PresentationFrames.
183 class PresentationFrameMap final {
184 public:
185 using RenderFrameHostId = std::pair<int, int>;
imcheng (use chromium acct) 2015/05/19 20:03:29 I don't think you need this. You can just reuse th
haibinlu 2015/05/19 21:14:35 Done.
186 using DelegateObserver = content::PresentationServiceDelegate::Observer;
187
188 explicit PresentationFrameMap(content::WebContents* web_contents,
imcheng (use chromium acct) 2015/05/19 20:03:29 rm explicit
haibinlu 2015/05/19 21:14:35 Done.
189 MediaRouter* router);
190 ~PresentationFrameMap();
191
192 // Returns true if listener was added.
193 bool AddScreenAvailabilityListener(
194 int render_process_id,
imcheng (use chromium acct) 2015/05/19 20:03:29 Use RenderFrameHostId here and below?
haibinlu 2015/05/19 21:14:35 Done.
195 int render_frame_id,
196 content::PresentationScreenAvailabilityListener* listener);
197
198 // Returns true if listener was removed.
199 bool RemoveScreenAvailabilityListener(
200 int render_process_id,
201 int render_frame_id,
202 content::PresentationScreenAvailabilityListener* listener);
203
204 // Returns true if there is a listener for |source_id| in the frame.
205 bool HasScreenAvailabilityListenerForTest(
206 RenderFrameHostId rfh_id,
207 const MediaSourceId& source_id) const;
208
209 // Returns the number of screen-availability listeners.
210 int NumScreenAvailabilityListeners() const;
211
212 // Returns the default presentation URL and ID for the frame.
213 void SetDefaultPresentationInfo(int render_process_id,
214 int render_frame_id,
215 const std::string& default_presentation_url,
216 const std::string& default_presentation_id);
217
218 // Returns empty string if no default presentation ID is set in the frame.
219 std::string GetDefaultPresentationId(RenderFrameHostId rfh_id) const;
220
221 void RegisterPresenationFrame(int render_process_id,
222 int render_frame_id,
223 DelegateObserver* observer);
224 void UnregisterPresenationFrame(int render_process_id, int render_frame_id);
225
226 DelegateObserver* GetDelegateObserver(RenderFrameHostId rfh_id) const;
227
228 void Reset(RenderFrameHostId rfh_id);
229
230 void SetMediaRouterForTest(MediaRouter* router);
231
232 private:
233 PresentationFrame* GetOrAddFrame(RenderFrameHostId rfh_id);
234
235 // Maps a frame identifier to a PresentationFrame object for frames
236 // that are using presentation API.
237 base::ScopedPtrHashMap<RenderFrameHostId, scoped_ptr<PresentationFrame>>
238 presentation_frames_;
239
240 // Does not own these two objects.
241 MediaRouter* router_;
242 content::WebContents* web_contents_;
243 };
244
245 PresentationFrameMap::PresentationFrameMap(content::WebContents* web_contents,
246 MediaRouter* router)
247 : web_contents_(web_contents), router_(router) {
248 DCHECK(web_contents_);
249 }
250
251 PresentationFrameMap::~PresentationFrameMap() {
252 }
253
254 bool PresentationFrameMap::AddScreenAvailabilityListener(
255 int render_process_id,
256 int render_frame_id,
257 content::PresentationScreenAvailabilityListener* listener) {
258 if (NumScreenAvailabilityListeners() >=
259 PresentationServiceDelegateImpl::kMaxNumSources) {
260 return false;
261 }
262
263 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
264 auto presentation_frame = GetOrAddFrame(rfh_id);
265 return presentation_frame->AddScreenAvailabilityListener(listener);
266 }
267
268 bool PresentationFrameMap::RemoveScreenAvailabilityListener(
269 int render_process_id,
270 int render_frame_id,
271 content::PresentationScreenAvailabilityListener* listener) {
272 DCHECK(listener);
273
274 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
275 auto presentation_frame = presentation_frames_.get(rfh_id);
276 return presentation_frame &&
277 presentation_frame->RemoveScreenAvailabilityListener(listener);
278 }
279
280 bool PresentationFrameMap::HasScreenAvailabilityListenerForTest(
281 RenderFrameHostId rfh_id,
282 const MediaSourceId& source_id) const {
283 auto presentation_frame = presentation_frames_.get(rfh_id);
284 return presentation_frame &&
285 presentation_frame->HasScreenAvailabilityListenerForTest(source_id);
286 }
287
288 int PresentationFrameMap::NumScreenAvailabilityListeners() const {
289 int count = 0;
290 for (const auto& pf : presentation_frames_) {
291 count += pf.second->NumScreenAvailabilityListeners();
292 }
293 return count;
294 }
295
296 void PresentationFrameMap::SetDefaultPresentationInfo(
297 int render_process_id,
298 int render_frame_id,
299 const std::string& default_presentation_url,
300 const std::string& default_presentation_id) {
301 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
302 auto presentation_frame = GetOrAddFrame(rfh_id);
303 presentation_frame->SetDefaultPresentationInfo(default_presentation_url,
304 default_presentation_id);
305 }
306
307 std::string PresentationFrameMap::GetDefaultPresentationId(
308 RenderFrameHostId rfh_id) const {
309 auto presentation_frame = presentation_frames_.get(rfh_id);
310 return presentation_frame ? presentation_frame->GetDefaultPresentationId()
311 : "";
312 }
313
314 void PresentationFrameMap::RegisterPresenationFrame(
315 int render_process_id,
316 int render_frame_id,
317 content::PresentationServiceDelegate::Observer* observer) {
318 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
319 auto presentation_frame = GetOrAddFrame(rfh_id);
320 presentation_frame->set_delegate_observer(observer);
321 }
322
323 void PresentationFrameMap::UnregisterPresenationFrame(int render_process_id,
324 int render_frame_id) {
325 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
326 auto presentation_frame = presentation_frames_.get(rfh_id);
327 if (presentation_frame) {
328 presentation_frame->set_delegate_observer(nullptr);
imcheng (use chromium acct) 2015/05/19 20:03:29 not needed if you move the OnDelegateDestroyed() t
haibinlu 2015/05/19 21:14:35 Done.
329 presentation_frames_.erase(rfh_id);
330 }
331 }
332
333 PresentationFrameMap::DelegateObserver*
334 PresentationFrameMap::GetDelegateObserver(RenderFrameHostId rfh_id) const {
335 auto presentation_frame = presentation_frames_.get(rfh_id);
336 return presentation_frame ? presentation_frame->delegate_observer() : nullptr;
337 }
338
339 void PresentationFrameMap::Reset(RenderFrameHostId rfh_id) {
340 auto presentation_frame = presentation_frames_.get(rfh_id);
341 if (presentation_frame)
342 presentation_frame->Reset();
343 }
344
345 PresentationFrame* PresentationFrameMap::GetOrAddFrame(
346 RenderFrameHostId rfh_id) {
347 if (!presentation_frames_.contains(rfh_id)) {
348 presentation_frames_.add(
349 rfh_id, scoped_ptr<PresentationFrame>(
350 new PresentationFrame(web_contents_, router_)));
351 }
352 return presentation_frames_.get(rfh_id);
353 }
354
355 void PresentationFrameMap::SetMediaRouterForTest(MediaRouter* router) {
356 router_ = router;
357 }
358
359 // TODO(haibinlu): Get router from MediaRouterMojoImplFactory once it lands.
360 PresentationServiceDelegateImpl::PresentationServiceDelegateImpl(
361 content::WebContents* web_contents)
362 : web_contents_(web_contents),
363 router_(NULL),
364 frame_map_(new PresentationFrameMap(web_contents, nullptr)),
imcheng (use chromium acct) 2015/05/19 20:03:29 you might as well pass in router_ here if you are
haibinlu 2015/05/19 21:14:35 will update this once MediaRouterMojoImplFactory l
365 weak_factory_(this) {
366 // DCHECK(router_);
367 }
368
369 PresentationServiceDelegateImpl::~PresentationServiceDelegateImpl() {
370 }
371
372 void PresentationServiceDelegateImpl::AddObserver(
373 int render_process_id,
374 int render_frame_id,
375 content::PresentationServiceDelegate::Observer* observer) {
376 DCHECK(observer);
377 frame_map_->RegisterPresenationFrame(render_process_id, render_frame_id,
378 observer);
379 }
380
381 void PresentationServiceDelegateImpl::RemoveObserver(int render_process_id,
382 int render_frame_id) {
383 frame_map_->UnregisterPresenationFrame(render_process_id, render_frame_id);
384 }
385
386 bool PresentationServiceDelegateImpl::AddScreenAvailabilityListener(
387 int render_process_id,
388 int render_frame_id,
389 content::PresentationScreenAvailabilityListener* listener) {
390 DCHECK(listener);
391 return frame_map_->AddScreenAvailabilityListener(render_process_id,
392 render_frame_id, listener);
393 }
394
395 void PresentationServiceDelegateImpl::RemoveScreenAvailabilityListener(
396 int render_process_id,
397 int render_frame_id,
398 content::PresentationScreenAvailabilityListener* listener) {
399 DCHECK(listener);
400 frame_map_->RemoveScreenAvailabilityListener(render_process_id,
401 render_frame_id, listener);
402 }
403
404 void PresentationServiceDelegateImpl::Reset(int render_process_id,
405 int render_frame_id) {
406 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
407 frame_map_->Reset(rfh_id);
408 if (IsMainFrame(rfh_id))
409 UpdateDefaultMediaSourceAndNotifyObservers(MediaSource(), std::string());
410 }
411
412 void PresentationServiceDelegateImpl::SetDefaultPresentationUrl(
413 int render_process_id,
414 int render_frame_id,
415 const std::string& default_presentation_url,
416 const std::string& default_presentation_id) {
417 frame_map_->SetDefaultPresentationInfo(render_process_id, render_frame_id,
418 default_presentation_url,
419 default_presentation_id);
420
421 RenderFrameHostId rfh_id(render_process_id, render_frame_id);
422 if (IsMainFrame(rfh_id)) {
423 // This is the main frame, that means tab-level default presentation
424 // might have been updated.
425 MediaSource new_default_source;
426 if (!default_presentation_url.empty())
427 new_default_source = ForPresentationUrl(default_presentation_url);
428 std::string new_default_source_host(GetSourceHostForFrame(rfh_id));
429 UpdateDefaultMediaSourceAndNotifyObservers(new_default_source,
430 new_default_source_host);
431 }
432 }
433
434 bool PresentationServiceDelegateImpl::IsMainFrame(
435 RenderFrameHostId rfh_id) const {
436 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
437 return main_frame && GetRenderFrameHostId(main_frame) == rfh_id;
438 }
439
440 void PresentationServiceDelegateImpl::
441 UpdateDefaultMediaSourceAndNotifyObservers(
442 const MediaSource& new_default_source,
443 const std::string& new_default_source_host) {
444 if (!new_default_source.Equals(default_source_) ||
445 new_default_source_host != default_source_host_) {
446 default_source_ = new_default_source;
447 default_source_host_ = new_default_source_host;
448 FOR_EACH_OBSERVER(
449 DefaultMediaSourceObserver, default_media_source_observers_,
450 OnDefaultMediaSourceChanged(default_source_, default_source_host_));
451 }
452 }
453
454 void PresentationServiceDelegateImpl::StartSession(
455 int render_process_id,
456 int render_frame_id,
457 const std::string& presentation_url,
458 const std::string& presentation_id,
459 const PresentationSessionSuccessCallback& success_cb,
460 const PresentationSessionErrorCallback& error_cb) {
461 NOTIMPLEMENTED();
462 }
463
464 void PresentationServiceDelegateImpl::JoinSession(
465 int render_process_id,
466 int render_frame_id,
467 const std::string& presentation_url,
468 const std::string& presentation_id,
469 const PresentationSessionSuccessCallback& success_cb,
470 const PresentationSessionErrorCallback& error_cb) {
471 NOTIMPLEMENTED();
472 }
473
474 void PresentationServiceDelegateImpl::ListenForSessionMessages(
475 int render_process_id,
476 int render_frame_id,
477 const PresentationSessionMessageCallback& message_cb) {
478 NOTIMPLEMENTED();
479 }
480
481 void PresentationServiceDelegateImpl::SendMessage(
482 int render_process_id,
483 int render_frame_id,
484 scoped_ptr<content::PresentationSessionMessage> message_request,
485 const SendMessageCallback& send_message_cb) {
486 NOTIMPLEMENTED();
487 }
488
489 void PresentationServiceDelegateImpl::OnRouteCreated(const MediaRoute& route) {
490 const MediaSource& source = route.media_source();
491 DCHECK(!source.Empty());
492 if (default_source_.Equals(source)) {
493 RenderFrameHost* main_frame = web_contents_->GetMainFrame();
494 if (main_frame) {
495 RenderFrameHostId rfh_id(GetRenderFrameHostId(main_frame));
496 auto observer = frame_map_->GetDelegateObserver(rfh_id);
497 if (observer) {
498 // TODO(imcheng): Pass in valid default presentation ID once it is
499 // available from MediaRoute URN.
500 observer->OnDefaultPresentationStarted(content::PresentationSessionInfo(
501 GetPresentationUrl(source), std::string()));
502 }
503 }
504 }
505 }
506
507 void PresentationServiceDelegateImpl::AddDefaultMediaSourceObserver(
508 DefaultMediaSourceObserver* observer) {
509 default_media_source_observers_.AddObserver(observer);
510 }
511
512 void PresentationServiceDelegateImpl::RemoveDefaultMediaSourceObserver(
513 DefaultMediaSourceObserver* observer) {
514 default_media_source_observers_.RemoveObserver(observer);
515 }
516
517 void PresentationServiceDelegateImpl::SetMediaRouterForTest(
518 MediaRouter* router) {
519 router_ = router;
520 frame_map_->SetMediaRouterForTest(router);
521 }
522
523 base::WeakPtr<PresentationServiceDelegateImpl>
524 PresentationServiceDelegateImpl::GetWeakPtr() {
525 return weak_factory_.GetWeakPtr();
526 }
527
528 bool PresentationServiceDelegateImpl::HasScreenAvailabilityListenerForTest(
529 RenderFrameHostId rfh_id,
530 const MediaSourceId& source_id) const {
531 return frame_map_->HasScreenAvailabilityListenerForTest(rfh_id, source_id);
532 }
533
534 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698