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

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

Issue 1314413005: [Presentation API] 1-UA presentation support + presenter APIs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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/offscreen_presentation_manager.h"
6
7 #include "content/public/browser/presentation_session_state_listener.h"
8 #include "content/public/browser/render_frame_host.h"
9 #include "content/public/browser/render_process_host.h"
10 #include "content/public/browser/web_contents.h"
11
12 using content::PresentationSessionInfo;
13 using content::PresentationReceiverSessionAvailableCallback;
14
15 namespace media_router {
16
17 namespace {
18
19 RenderFrameHostId GetMainFrameRenderFrameHostId(
20 content::WebContents* web_contents) {
21 content::RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
22 DCHECK(render_frame_host);
23 return RenderFrameHostId(render_frame_host->GetProcess()->GetID(),
24 render_frame_host->GetRoutingID());
25 }
26
27 } // namespace
28
29 OffscreenPresenterContext::OffscreenPresenterContext(
30 content::WebContents* presenter_web_contents,
31 const std::string& presentation_id,
32 OffscreenPresentationManager* manager)
33 : presenter_web_contents_(presenter_web_contents),
34 presentation_id_(presentation_id),
35 manager_(manager) {
36 DCHECK(presenter_web_contents_);
37 DCHECK(manager_);
38 }
39
40 OffscreenPresenterContext::~OffscreenPresenterContext() {
41 manager_->UnregisterPresenterTab(presenter_web_contents_);
42 }
43
44 void OffscreenPresenterContext::GetPresentationReceiverSession(
45 const RenderFrameHostId& frame_id,
46 const content::PresentationReceiverSessionAvailableCallback&
47 success_callback,
48 const base::Callback<void(const std::string&)>& error_callback) {
49 if (!IsPresenterFrame(frame_id)) {
50 DVLOG(1) << "Not a presenter frame: " << frame_id.first << ", "
51 << frame_id.second;
52 error_callback.Run("Not a presenter frame");
53 return;
54 }
55
56 manager_->GetReceiverSession(frame_id, success_callback);
57 }
58
59 std::vector<content::PresentationSessionInfo>
60 OffscreenPresenterContext::GetPresentationReceiverSessions(
61 const RenderFrameHostId& frame_id) const {
62 if (!IsPresenterFrame(frame_id)) {
63 DVLOG(1) << "Not a presenter frame: " << frame_id.first << ", "
64 << frame_id.second;
65 return std::vector<content::PresentationSessionInfo>();
66 }
67
68 return manager_->GetPresentationReceiverSessions(frame_id);
69 }
70
71 bool OffscreenPresenterContext::IsPresenterFrame(
72 const RenderFrameHostId& frame_id) const {
73 return GetMainFrameRenderFrameHostId(presenter_web_contents_) == frame_id;
74 }
75
76 void OffscreenPresenterContext::SendMessage(
77 const RenderFrameHostId& frame_id,
78 const content::PresentationSessionInfo& session,
79 scoped_ptr<content::PresentationSessionMessage> message,
80 const content::SendMessageCallback& callback) {
81 DCHECK_EQ(presentation_id_, session.presentation_id);
82 DCHECK(!session.IsController());
83 DCHECK(IsPresenterFrame(frame_id));
84
85 manager_->SendMessage(session, message.Pass(), callback);
86 }
87
88 void OffscreenPresenterContext::ListenForMessages(
89 const RenderFrameHostId& frame_id,
miu 2015/09/27 00:22:08 1. |frame_id| argument is not used, so can you rem
imcheng 2015/09/30 01:13:41 1. Removed. Also removed some other unused fields
90 const content::PresentationSessionInfo& session,
91 const content::PresentationSessionMessageCallback& callback) {
92 DCHECK_EQ(presentation_id_, session.presentation_id);
93 DCHECK(!session.IsController());
94 DCHECK(IsPresenterFrame(frame_id));
95
96 manager_->ListenForMessages(session, callback);
97 }
98
99 void OffscreenPresenterContext::ListenForStateChanges(
100 const RenderFrameHostId& frame_id,
101 content::PresentationSessionStateListener* listener) {
102 DCHECK(listener);
103 DCHECK(IsPresenterFrame(frame_id));
104
105 const content::PresentationSessionInfo& session = listener->GetSessionInfo();
miu 2015/09/27 00:22:08 These three lines need to be wrapped in a #ifndef
imcheng 2015/09/30 01:13:41 Removed
106 DCHECK_EQ(presentation_id_, session.presentation_id);
107 DCHECK(!session.IsController());
108
109 manager_->ListenForStateChanges(listener);
110 }
111
112 OffscreenController::OffscreenController(
113 const RenderFrameHostId& controller_frame_id,
114 const content::PresentationSessionInfo& session,
115 OffscreenPresentationManager* manager)
116 : controller_frame_id_(controller_frame_id),
117 session_(session),
118 manager_(manager) {
119 DCHECK(manager_);
120 DCHECK(session.IsController());
121 }
122
123 OffscreenController::~OffscreenController() {
124 manager_->UnregisterController(controller_frame_id_,
125 session_.presentation_id);
126 }
127
128 void OffscreenController::SendMessage(
129 scoped_ptr<content::PresentationSessionMessage> message,
130 const content::SendMessageCallback& callback) {
131 manager_->SendMessage(session_, message.Pass(), callback);
132 }
133
134 void OffscreenController::ListenForMessages(
135 const content::PresentationSessionMessageCallback& callback) {
136 manager_->ListenForMessages(session_, callback);
137 }
138
139 void OffscreenController::ListenForStateChanges(
140 content::PresentationSessionStateListener* listener) {
141 DCHECK(listener);
142 DCHECK_EQ(session_.presentation_id,
143 listener->GetSessionInfo().presentation_id);
144 manager_->ListenForStateChanges(listener);
145 }
146
147 OffscreenPresentationManager::~OffscreenPresentationManager() {}
148
149 void OffscreenPresentationManager::RegisterPresenterTab(
150 const std::string& presentation_id,
151 content::WebContents* presenter_web_contents) {
152 DCHECK(presenter_web_contents);
153 RenderFrameHostId presenter_frame_id(
154 GetMainFrameRenderFrameHostId(presenter_web_contents));
155 DCHECK(!ContainsKey(presenter_frames_, presenter_frame_id));
156 presenter_frames_[presenter_frame_id] = presentation_id;
157
158 auto* presentation_info =
159 GetOrCreateOffscreenPresentationInfo(presentation_id);
160 presentation_info->presenter_frame_id = presenter_frame_id;
161 // We wait until the controller side has registered before setting up the
162 // route.
163 }
164
165 void OffscreenPresentationManager::UnregisterPresenterTab(
166 content::WebContents* presenter_web_contents) {
167 DCHECK(presenter_web_contents);
168 RenderFrameHostId presenter_frame_id(
169 GetMainFrameRenderFrameHostId(presenter_web_contents));
170
171 auto it = presenter_frames_.find(presenter_frame_id);
172 if (it == presenter_frames_.end())
173 return;
174
175 std::string presentation_id = it->second;
176 presenter_frames_.erase(it);
177
178 auto* presentation_info = GetOffscreenPresentationInfo(presentation_id);
179 DCHECK(presentation_info);
180 DCHECK(presenter_frame_id == presentation_info->presenter_frame_id);
181 RemovePresenterAndNotifyStateChange(presentation_info);
182 if (presentation_info->IsEmpty())
183 offscreen_presentation_infos_.erase(presentation_id);
184 }
185
186 scoped_ptr<OffscreenPresenterContext>
187 OffscreenPresentationManager::GetOffscreenPresenterContext(
188 content::WebContents* presenter_web_contents) {
189 DCHECK(presenter_web_contents);
190 RenderFrameHostId presenter_frame_id(
191 GetMainFrameRenderFrameHostId(presenter_web_contents));
192 auto it = presenter_frames_.find(presenter_frame_id);
193 if (it == presenter_frames_.end())
194 return scoped_ptr<OffscreenPresenterContext>();
195
196 return make_scoped_ptr(
197 new OffscreenPresenterContext(presenter_web_contents, it->second, this));
198 }
199
200 scoped_ptr<OffscreenController>
201 OffscreenPresentationManager::RegisterController(
202 const content::PresentationSessionInfo& session,
203 const RenderFrameHostId& controller_frame_id) {
204 const std::string& presentation_id = session.presentation_id;
205 auto* presentation_info =
206 GetOrCreateOffscreenPresentationInfo(presentation_id);
207
208 auto& route = presentation_info->route;
209
210 // Check that this (presentation, controller) is not already registered.
211 DCHECK(!route.controller);
212 DCHECK(!route.presenter);
213
214 route.controller.reset(
215 new OffscreenPresentationSessionInfo(controller_frame_id, session));
216 content::PresentationSessionInfo presenter_session(std::string(),
217 presentation_id);
218 route.presenter.reset(new OffscreenPresentationSessionInfo(
219 controller_frame_id, presenter_session));
220
221 // Resolve pending getSession() request.
222 // Note: session objects for presenters do not contain presentation URLs.
223 if (!presentation_info->session_callback.is_null()) {
224 presentation_info->session_callback.Run(presenter_session);
225 presentation_info->session_callback.Reset();
226 }
227
228 return make_scoped_ptr(
229 new OffscreenController(controller_frame_id, session, this));
230 }
231
232 void OffscreenPresentationManager::GetReceiverSession(
233 const RenderFrameHostId& presenter_frame_id,
234 const PresentationReceiverSessionAvailableCallback& callback) {
235 DCHECK(!callback.is_null());
236 DCHECK(ContainsKey(presenter_frames_, presenter_frame_id));
237
238 const std::string& presentation_id = presenter_frames_[presenter_frame_id];
239 auto* presentation_info = GetOffscreenPresentationInfo(presentation_id);
240 DCHECK(presentation_info);
241 DCHECK(presenter_frame_id == presentation_info->presenter_frame_id);
242
243 // Resolve with the first route.
244 const auto& route = presentation_info->route;
245 if (route.presenter) {
246 callback.Run(route.presenter->session);
247 return;
248 } else {
249 presentation_info->session_callback = callback;
250 }
251 }
252
253 std::vector<content::PresentationSessionInfo>
254 OffscreenPresentationManager::GetPresentationReceiverSessions(
255 const RenderFrameHostId& presenter_frame_id) const {
256 DCHECK(ContainsKey(presenter_frames_, presenter_frame_id));
257
258 auto it = presenter_frames_.find(presenter_frame_id);
259 DCHECK(it != presenter_frames_.end());
260 const std::string& presentation_id = it->second;
261 auto* presentation_info = GetOffscreenPresentationInfo(presentation_id);
262 DCHECK(presentation_info);
263
264 std::vector<content::PresentationSessionInfo> sessions;
265 // TODO(imcheng): Support multiple controllers.
266 if (presentation_info->route.presenter)
267 sessions.push_back(presentation_info->route.presenter->session);
268 return sessions;
269 }
270
271 void OffscreenPresentationManager::SendMessage(
272 const PresentationSessionInfo& session,
273 scoped_ptr<content::PresentationSessionMessage> message,
274 const content::SendMessageCallback& callback) {
275 const std::string& presentation_id = session.presentation_id;
276 auto* presentation_info = GetOffscreenPresentationInfo(presentation_id);
277 if (!presentation_info) {
278 LOG(ERROR) << "SendMessage: Unknown 1UA presentation " << presentation_id;
279 callback.Run(false);
280 return;
281 }
282
283 auto& route = presentation_info->route;
284 // From presenter to controller.
285 if (!session.IsController()) {
286 auto* controller = route.controller.get();
287 if (controller && !controller->message_callback.is_null()) {
288 ScopedVector<content::PresentationSessionMessage> messages;
289 messages.push_back(message.release());
290 controller->message_callback.Run(messages.Pass(), true);
291 }
292 } else {
293 auto* presenter = route.presenter.get();
294 // From controller to presenter.
295 if (presenter && !presenter->message_callback.is_null()) {
296 ScopedVector<content::PresentationSessionMessage> messages;
297 messages.push_back(message.release());
298 presenter->message_callback.Run(messages.Pass(), true);
299 }
300 }
301
302 callback.Run(true);
303 }
304
305 void OffscreenPresentationManager::ListenForMessages(
306 const PresentationSessionInfo& session,
307 const content::PresentationSessionMessageCallback& callback) {
308 const std::string& presentation_id = session.presentation_id;
309 auto* presentation_info = GetOffscreenPresentationInfo(presentation_id);
310 if (!presentation_info) {
311 LOG(ERROR) << "ListenForMessages: Unknown 1UA presentation "
312 << presentation_id;
313 return;
314 }
315
316 auto& route = presentation_info->route;
317 if (!session.IsController()) {
318 auto* presenter = route.presenter.get();
319 if (!presenter) {
320 LOG(ERROR) << "ListenForMessages: presenter frame not found for "
321 << presentation_id;
322 return;
323 }
324 DVLOG_IF(2, !presenter->message_callback.is_null())
325 << "Overwriting presenter frame message callback for "
326 << presentation_id;
327 presenter->message_callback = callback;
328 } else {
329 auto* controller = route.controller.get();
330 if (!controller) {
331 LOG(ERROR) << "ListenForMessages: controller frame not found for "
332 << presentation_id;
333 return;
334 }
335 DVLOG_IF(2, !controller->message_callback.is_null())
336 << "Overwriting controller frame message callback for "
337 << presentation_id;
338 controller->message_callback = callback;
339 }
340 }
341
342 void OffscreenPresentationManager::ListenForStateChanges(
343 content::PresentationSessionStateListener* listener) {
344 DCHECK(listener);
345
346 const content::PresentationSessionInfo& session = listener->GetSessionInfo();
347 const std::string& presentation_id = session.presentation_id;
348 auto* presentation_info = GetOffscreenPresentationInfo(presentation_id);
349 if (!presentation_info) {
350 LOG(ERROR) << "ListenForMessages: Unknown 1UA presentation "
351 << presentation_id;
352 return;
353 }
354
355 auto& route = presentation_info->route;
356 if (!session.IsController()) {
357 auto* presenter = route.presenter.get();
358 if (!presenter) {
359 LOG(ERROR) << "ListenForMessages: presenter frame not found for "
360 << presentation_id;
361 return;
362 }
363 DVLOG_IF(2, presenter->state_change_listener)
364 << "Overwriting presenter frame state change listener for "
365 << presentation_id;
366 presenter->state_change_listener = listener;
367 } else {
368 auto* controller = route.controller.get();
369 if (!controller) {
370 LOG(ERROR) << "ListenForMessages: controller frame not found for "
371 << presentation_id;
372 return;
373 }
374 DVLOG_IF(2, controller->state_change_listener)
375 << "Overwriting controller frame state change listener for "
376 << presentation_id;
377 controller->state_change_listener = listener;
378 }
379 }
380
381 void OffscreenPresentationManager::UnregisterController(
382 const RenderFrameHostId& controller_frame_id,
383 const std::string& presentation_id) {
384 auto it = offscreen_presentation_infos_.find(presentation_id);
385 if (it == offscreen_presentation_infos_.end())
386 return;
387
388 auto* presentation_info = it->second;
389 RemoveControllerAndNotifyStateChange(presentation_info, controller_frame_id);
390 if (presentation_info->IsEmpty())
391 offscreen_presentation_infos_.erase(it);
392 }
393
394 OffscreenPresentationManager::OffscreenPresentationManager() {}
395
396 void OffscreenPresentationManager::RemovePresenterAndNotifyStateChange(
397 OffscreenPresentationInfo* presentation_info) {
398 presentation_info->presenter_frame_id = RenderFrameHostId();
399 presentation_info->session_callback.Reset();
400
401 auto& route = presentation_info->route;
402 if (route.presenter) {
403 route.presenter.reset();
404 auto& controller = route.controller;
405 if (controller && controller->state_change_listener) {
406 controller->state_change_listener->OnSessionStateChanged(
407 content::PRESENTATION_SESSION_STATE_DISCONNECTED);
408 }
409 }
410 }
411
412 void OffscreenPresentationManager::RemoveControllerAndNotifyStateChange(
413 OffscreenPresentationInfo* presentation_info,
414 const RenderFrameHostId& controller_frame_id) {
415 auto& route = presentation_info->route;
416 if (!route.controller ||
417 route.controller->controller_frame_id != controller_frame_id)
418 return;
419
420 route.controller.reset();
421
422 // Notify the corresponding presenter session object.
423 auto& presenter = route.presenter;
424 if (presenter && presenter->state_change_listener) {
425 presenter->state_change_listener->OnSessionStateChanged(
426 content::PRESENTATION_SESSION_STATE_DISCONNECTED);
427 }
428 }
429
430 OffscreenPresentationManager::OffscreenPresentationInfo*
431 OffscreenPresentationManager::GetOrCreateOffscreenPresentationInfo(
432 const std::string& presentation_id) {
433 OffscreenPresentationInfo* info = nullptr;
434 auto presentation_info_it =
435 offscreen_presentation_infos_.find(presentation_id);
436 if (presentation_info_it == offscreen_presentation_infos_.end()) {
437 info = new OffscreenPresentationInfo;
438 offscreen_presentation_infos_.insert(presentation_id,
439 make_scoped_ptr(info));
440 } else {
441 info = presentation_info_it->second;
442 }
443 DCHECK(info);
444 return info;
445 }
446
447 OffscreenPresentationManager::OffscreenPresentationInfo*
448 OffscreenPresentationManager::GetOffscreenPresentationInfo(
449 const std::string& presentation_id) const {
450 OffscreenPresentationInfo* info = nullptr;
451 auto presentation_info_it =
452 offscreen_presentation_infos_.find(presentation_id);
453 return presentation_info_it == offscreen_presentation_infos_.end()
454 ? nullptr
455 : presentation_info_it->second;
456 }
457
458 OffscreenPresentationManager::OffscreenPresentationSessionInfo::
459 OffscreenPresentationSessionInfo(
460 const RenderFrameHostId& controller_frame_id,
461 const content::PresentationSessionInfo& session)
462 : controller_frame_id(controller_frame_id),
463 session(session),
464 state_change_listener(nullptr) {}
465
466 OffscreenPresentationManager::OffscreenPresentationSessionInfo::
467 ~OffscreenPresentationSessionInfo() {}
468
469 OffscreenPresentationManager::OffscreenPresentationRoute::
470 OffscreenPresentationRoute() {}
471
472 OffscreenPresentationManager::OffscreenPresentationRoute::
473 ~OffscreenPresentationRoute() {}
474
475 OffscreenPresentationManager::OffscreenPresentationInfo::
476 OffscreenPresentationInfo() {}
477
478 OffscreenPresentationManager::OffscreenPresentationInfo::
479 ~OffscreenPresentationInfo() {}
480
481 bool OffscreenPresentationManager::OffscreenPresentationInfo::IsEmpty() const {
482 return !route.presenter && !route.controller;
483 }
484
485 } // namespace media_router
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698