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

Side by Side Diff: content/renderer/presentation/presentation_dispatcher.cc

Issue 2598063002: [Presentation API] Handle multiple Presentation URLs in PresentationRequest::getAvailability() (Closed)
Patch Set: resolve code review comments from Mark Created 3 years, 11 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/presentation/presentation_dispatcher.h" 5 #include "content/renderer/presentation/presentation_dispatcher.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 return blink::WebPresentationConnectionCloseReason::Error; 68 return blink::WebPresentationConnectionCloseReason::Error;
69 case blink::mojom::PresentationConnectionCloseReason::CLOSED: 69 case blink::mojom::PresentationConnectionCloseReason::CLOSED:
70 return blink::WebPresentationConnectionCloseReason::Closed; 70 return blink::WebPresentationConnectionCloseReason::Closed;
71 case blink::mojom::PresentationConnectionCloseReason::WENT_AWAY: 71 case blink::mojom::PresentationConnectionCloseReason::WENT_AWAY:
72 return blink::WebPresentationConnectionCloseReason::WentAway; 72 return blink::WebPresentationConnectionCloseReason::WentAway;
73 default: 73 default:
74 NOTREACHED(); 74 NOTREACHED();
75 return blink::WebPresentationConnectionCloseReason::Error; 75 return blink::WebPresentationConnectionCloseReason::Error;
76 } 76 }
77 } 77 }
78
79 } // namespace 78 } // namespace
80 79
81 namespace content { 80 namespace content {
82 81
83 PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame) 82 PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame)
84 : RenderFrameObserver(render_frame), 83 : RenderFrameObserver(render_frame),
85 controller_(nullptr), 84 controller_(nullptr),
86 binding_(this) { 85 binding_(this) {
87 } 86 }
88 87
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 237
239 void PresentationDispatcher::terminateSession( 238 void PresentationDispatcher::terminateSession(
240 const blink::WebURL& presentationUrl, 239 const blink::WebURL& presentationUrl,
241 const blink::WebString& presentationId) { 240 const blink::WebString& presentationId) {
242 ConnectToPresentationServiceIfNeeded(); 241 ConnectToPresentationServiceIfNeeded();
243 presentation_service_->Terminate(presentationUrl, presentationId.utf8()); 242 presentation_service_->Terminate(presentationUrl, presentationId.utf8());
244 } 243 }
245 244
246 void PresentationDispatcher::getAvailability( 245 void PresentationDispatcher::getAvailability(
247 const blink::WebVector<blink::WebURL>& availabilityUrls, 246 const blink::WebVector<blink::WebURL>& availabilityUrls,
248 std::unique_ptr<blink::WebPresentationAvailabilityCallbacks> callbacks) { 247 std::unique_ptr<blink::WebPresentationAvailabilityCallbacks> callback) {
249 // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. 248 DCHECK(!availabilityUrls.isEmpty());
250 const blink::WebURL& availabilityUrl = availabilityUrls[0];
251 AvailabilityStatus* status = nullptr;
252 auto status_it = availability_status_.find(availabilityUrl);
253 if (status_it == availability_status_.end()) {
254 status = new AvailabilityStatus(availabilityUrl);
255 availability_status_[availabilityUrl] = base::WrapUnique(status);
256 } else {
257 status = status_it->second.get();
258 }
259 DCHECK(status);
260 249
261 if (status->listening_state == ListeningState::ACTIVE) { 250 auto availability_callback = base::MakeUnique<AvailabilityCallback>(
262 base::ThreadTaskRunnerHandle::Get()->PostTask( 251 availabilityUrls, std::move(callback));
263 FROM_HERE, 252
264 base::Bind(&blink::WebPresentationAvailabilityCallbacks::onSuccess, 253 for (const auto& availabilityUrl : availabilityUrls) {
265 base::Passed(&callbacks), status->last_known_availability)); 254 AvailabilityStatus* status = nullptr;
266 return; 255 auto status_it = availability_status_.find(availabilityUrl);
256 if (status_it == availability_status_.end()) {
257 status = new AvailabilityStatus(availabilityUrl);
258 availability_status_[availabilityUrl] = base::WrapUnique(status);
259 } else {
260 status = status_it->second.get();
261 }
262 DCHECK(status);
263 status->availability_callbacks.insert(availability_callback.get());
267 } 264 }
268 265
269 status->availability_callbacks.Add(std::move(callbacks)); 266 for (const auto& availabilityUrl : availabilityUrls) {
270 UpdateListeningState(status); 267 auto status_it = availability_status_.find(availabilityUrl);
268 DCHECK(status_it != availability_status_.end());
mlamouri (slow - plz ping) 2017/01/04 16:15:00 I think you can use DCHECK_NE here.
zhaobin 2017/01/06 01:55:21 Code removed.
269 AvailabilityStatus* status = status_it->second.get();
270
271 UpdateAvailabilityObserversAndCallbacks(status);
mark a. foltz 2017/01/03 21:47:13 Can this loop be combined with the previous one?
zhaobin 2017/01/06 01:55:21 Code removed.
272 UpdateListeningState(status);
273 }
274
275 availability_callbacks_.push_back(std::move(availability_callback));
271 } 276 }
272 277
273 void PresentationDispatcher::startListening( 278 void PresentationDispatcher::startListening(
274 blink::WebPresentationAvailabilityObserver* observer) { 279 blink::WebPresentationAvailabilityObserver* observer) {
275 // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. 280 for (const auto& availabilityUrl : observer->urls()) {
276 const blink::WebURL& availabilityUrl = observer->urls()[0]; 281 auto status_it = availability_status_.find(availabilityUrl);
277 auto status_it = availability_status_.find(availabilityUrl); 282 if (status_it == availability_status_.end()) {
278 if (status_it == availability_status_.end()) { 283 DLOG(WARNING) << "Start listening for availability for unknown URL "
279 DLOG(WARNING) << "Start listening for availability for unknown URL " 284 << GURL(availabilityUrl);
280 << GURL(availabilityUrl); 285 return;
281 return; 286 }
287 status_it->second->availability_observers.insert(observer);
288 UpdateListeningState(status_it->second.get());
282 } 289 }
283 status_it->second->availability_observers.insert(observer);
284 UpdateListeningState(status_it->second.get());
285 } 290 }
286 291
287 void PresentationDispatcher::stopListening( 292 void PresentationDispatcher::stopListening(
288 blink::WebPresentationAvailabilityObserver* observer) { 293 blink::WebPresentationAvailabilityObserver* observer) {
289 // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. 294 for (const auto& availabilityUrl : observer->urls()) {
290 const blink::WebURL& availabilityUrl = observer->urls()[0]; 295 auto status_it = availability_status_.find(availabilityUrl);
291 auto status_it = availability_status_.find(availabilityUrl); 296 if (status_it == availability_status_.end()) {
292 if (status_it == availability_status_.end()) { 297 DLOG(WARNING) << "Stop listening for availability for unknown URL "
293 DLOG(WARNING) << "Stop listening for availability for unknown URL " 298 << GURL(availabilityUrl);
294 << GURL(availabilityUrl); 299 return;
295 return; 300 }
301 status_it->second->availability_observers.erase(observer);
302 UpdateListeningState(status_it->second.get());
296 } 303 }
297 status_it->second->availability_observers.erase(observer);
298 UpdateListeningState(status_it->second.get());
299 } 304 }
300 305
301 void PresentationDispatcher::setDefaultPresentationUrls( 306 void PresentationDispatcher::setDefaultPresentationUrls(
302 const blink::WebVector<blink::WebURL>& presentationUrls) { 307 const blink::WebVector<blink::WebURL>& presentationUrls) {
303 ConnectToPresentationServiceIfNeeded(); 308 ConnectToPresentationServiceIfNeeded();
304 309
305 std::vector<GURL> urls; 310 std::vector<GURL> urls;
306 for (const auto& url : presentationUrls) 311 for (const auto& url : presentationUrls)
307 urls.push_back(url); 312 urls.push_back(url);
308 313
(...skipping 27 matching lines...) Expand all
336 bool available) { 341 bool available) {
337 auto status_it = availability_status_.find(url); 342 auto status_it = availability_status_.find(url);
338 if (status_it == availability_status_.end()) 343 if (status_it == availability_status_.end())
339 return; 344 return;
340 AvailabilityStatus* status = status_it->second.get(); 345 AvailabilityStatus* status = status_it->second.get();
341 DCHECK(status); 346 DCHECK(status);
342 347
343 if (status->listening_state == ListeningState::WAITING) 348 if (status->listening_state == ListeningState::WAITING)
344 status->listening_state = ListeningState::ACTIVE; 349 status->listening_state = ListeningState::ACTIVE;
345 350
346 for (auto* observer : status->availability_observers) 351 status->last_known_availability = available ? ScreenAvailability::AVAILABLE
347 observer->availabilityChanged(available); 352 : ScreenAvailability::UNAVAILABLE;
348 353 UpdateAvailabilityObserversAndCallbacks(status);
mark a. foltz 2017/01/03 21:47:13 This only needs to be called if last_known_availab
zhaobin 2017/01/06 01:55:20 Done.
349 for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks);
350 !iter.IsAtEnd(); iter.Advance()) {
351 iter.GetCurrentValue()->onSuccess(available);
352 }
353 status->last_known_availability = available;
354 status->availability_callbacks.Clear();
355 UpdateListeningState(status); 354 UpdateListeningState(status);
356 } 355 }
357 356
358 void PresentationDispatcher::OnScreenAvailabilityNotSupported(const GURL& url) { 357 void PresentationDispatcher::OnScreenAvailabilityNotSupported(const GURL& url) {
359 auto status_it = availability_status_.find(url); 358 auto status_it = availability_status_.find(url);
360 if (status_it == availability_status_.end()) 359 if (status_it == availability_status_.end())
361 return; 360 return;
362 AvailabilityStatus* status = status_it->second.get(); 361 AvailabilityStatus* status = status_it->second.get();
363 DCHECK(status); 362 DCHECK(status);
364 DCHECK(status->listening_state == ListeningState::WAITING); 363 DCHECK(status->listening_state == ListeningState::WAITING);
365 364
366 const blink::WebString& not_supported_error = blink::WebString::fromUTF8( 365 status->last_known_availability = ScreenAvailability::UNSUPPORTED;
367 "getAvailability() isn't supported at the moment. It can be due to " 366 UpdateAvailabilityObserversAndCallbacks(status);
mark a. foltz 2017/01/03 21:47:12 This only needs to be called if last_known_availab
zhaobin 2017/01/06 01:55:20 Done.
368 "a permanent or temporary system limitation. It is recommended to " 367 UpdateListeningState(status);
369 "try to blindly start a session in that case."); 368 }
mlamouri (slow - plz ping) 2017/01/04 16:15:00 Why are you removing the entire error message?
370 for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks); 369
371 !iter.IsAtEnd(); iter.Advance()) { 370 void PresentationDispatcher::UpdateAvailabilityObserversAndCallbacks(
mark a. foltz 2017/01/03 21:47:13 Shorter as UpdateAvailabilityStatus ?
zhaobin 2017/01/06 01:55:20 Done.
372 iter.GetCurrentValue()->onError(blink::WebPresentationError( 371 AvailabilityStatus* status) {
mark a. foltz 2017/01/03 21:47:13 Could this be a method on AvailabilityStatus()?
zhaobin 2017/01/06 01:55:20 Done.
373 blink::WebPresentationError::ErrorTypeAvailabilityNotSupported, 372 for (auto* observer : status->availability_observers) {
374 not_supported_error)); 373 auto availability = GetScreenAvailability(observer->urls());
374 if (availability != ScreenAvailability::UNKNOWN)
375 observer->availabilityChanged(availability ==
mark a. foltz 2017/01/03 21:47:13 Where do you check that the availability has chang
zhaobin 2017/01/06 01:55:20 No check in PresentationDispatcher. PresentationRe
376 ScreenAvailability::AVAILABLE);
375 } 377 }
376 status->availability_callbacks.Clear(); 378
377 UpdateListeningState(status); 379 AvailabilityCallbacksSet callbacks_to_be_removed;
380 for (auto* availability_callback : status->availability_callbacks) {
381 auto availability = GetScreenAvailability(availability_callback->urls);
382 if (availability == ScreenAvailability::UNKNOWN) {
mark a. foltz 2017/01/03 21:47:13 Nit: This could be a switch statement with a NOTRE
zhaobin 2017/01/06 01:55:20 Code removed.
383 continue;
384 } else if (availability == ScreenAvailability::UNSUPPORTED) {
385 availability_callback->callback->onError(blink::WebPresentationError(
386 blink::WebPresentationError::ErrorTypeAvailabilityNotSupported,
387 "Screen availability monitoring not supported"));
388 } else {
389 bool is_available = availability == ScreenAvailability::AVAILABLE;
390 availability_callback->callback->onSuccess(is_available);
mlamouri (slow - plz ping) 2017/01/04 16:15:00 nit: merge in one line
zhaobin 2017/01/06 01:55:20 Done.
391 }
392
393 callbacks_to_be_removed.insert(availability_callback);
394 }
395
396 // Clean up callbacks from |availability_status_|.
397 for (auto* callback_to_be_removed : callbacks_to_be_removed) {
398 for (auto& status_it : availability_status_) {
399 auto status = status_it.second.get();
400 if (!base::ContainsValue(status->availability_callbacks,
401 callback_to_be_removed))
402 continue;
mlamouri (slow - plz ping) 2017/01/04 16:15:00 style: { }
zhaobin 2017/01/06 01:55:20 Code removed.
403 status->availability_callbacks.erase(callback_to_be_removed);
404 UpdateListeningState(status);
405 }
406 }
407
408 // Clean up callbacks from |availability_callbacks_|.
409 std::remove_if(availability_callbacks_.begin(), availability_callbacks_.end(),
410 [&](const std::unique_ptr<AvailabilityCallback>& callback) {
411 return base::ContainsValue(callbacks_to_be_removed,
412 callback.get());
413 });
378 } 414 }
379 415
380 void PresentationDispatcher::OnDefaultSessionStarted( 416 void PresentationDispatcher::OnDefaultSessionStarted(
381 blink::mojom::PresentationSessionInfoPtr session_info) { 417 blink::mojom::PresentationSessionInfoPtr session_info) {
382 if (!controller_) 418 if (!controller_)
383 return; 419 return;
384 420
385 if (!session_info.is_null()) { 421 if (!session_info.is_null()) {
386 presentation_service_->ListenForConnectionMessages(session_info.Clone()); 422 presentation_service_->ListenForConnectionMessages(session_info.Clone());
387 controller_->didStartDefaultSession( 423 controller_->didStartDefaultSession(
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 } 513 }
478 514
479 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() { 515 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
480 if (presentation_service_.get()) 516 if (presentation_service_.get())
481 return; 517 return;
482 518
483 render_frame()->GetRemoteInterfaces()->GetInterface(&presentation_service_); 519 render_frame()->GetRemoteInterfaces()->GetInterface(&presentation_service_);
484 presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind()); 520 presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind());
485 } 521 }
486 522
523 void PresentationDispatcher::SetPresentationServiceForTest(
524 blink::mojom::PresentationServicePtr presentation_service) {
525 presentation_service_ = std::move(presentation_service);
526 }
527
487 void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) { 528 void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) {
488 bool should_listen = !status->availability_callbacks.IsEmpty() || 529 bool should_listen = !status->availability_callbacks.empty() ||
489 !status->availability_observers.empty(); 530 !status->availability_observers.empty();
490 bool is_listening = status->listening_state != ListeningState::INACTIVE; 531 bool is_listening = status->listening_state != ListeningState::INACTIVE;
491 532
492 if (should_listen == is_listening) 533 if (should_listen == is_listening)
493 return; 534 return;
494 535
495 ConnectToPresentationServiceIfNeeded(); 536 ConnectToPresentationServiceIfNeeded();
496 if (should_listen) { 537 if (should_listen) {
497 status->listening_state = ListeningState::WAITING; 538 status->listening_state = ListeningState::WAITING;
498 presentation_service_->ListenForScreenAvailability(status->url); 539 presentation_service_->ListenForScreenAvailability(status->url);
499 } else { 540 } else {
500 status->listening_state = ListeningState::INACTIVE; 541 status->listening_state = ListeningState::INACTIVE;
501 presentation_service_->StopListeningForScreenAvailability(status->url); 542 presentation_service_->StopListeningForScreenAvailability(status->url);
502 } 543 }
503 } 544 }
504 545
546 PresentationDispatcher::ScreenAvailability
547 PresentationDispatcher::GetScreenAvailability(
548 const blink::WebVector<blink::WebURL>& urls) {
549 size_t available_cnt = 0;
550 size_t unavailable_cnt = 0;
551 size_t unsupport_cnt = 0;
552 size_t unknown_cnt = 0;
mlamouri (slow - plz ping) 2017/01/04 16:15:00 style: s/cnt/count/. the abreviation doesn't seem
zhaobin 2017/01/06 01:55:20 Code removed.
553
554 for (const auto& url : urls) {
555 if (!base::ContainsKey(availability_status_, url))
556 return ScreenAvailability::UNKNOWN;
557
558 auto url_availability = availability_status_[url]->last_known_availability;
559 switch (url_availability) {
560 case ScreenAvailability::AVAILABLE:
561 available_cnt++;
562 break;
563 case ScreenAvailability::UNAVAILABLE:
564 unavailable_cnt++;
565 break;
566 case ScreenAvailability::UNSUPPORTED:
567 unsupport_cnt++;
568 break;
569 case ScreenAvailability::UNKNOWN:
570 unknown_cnt++;
571 break;
572 }
573 }
mlamouri (slow - plz ping) 2017/01/04 16:15:00 FWIW, you can simplify this by having a map that a
zhaobin 2017/01/06 01:55:20 Done.
574
575 if (unknown_cnt > 0)
576 return ScreenAvailability::UNKNOWN;
mark a. foltz 2017/01/03 21:47:13 IMO, we should only return UNKNOWN if all URLs are
zhaobin 2017/01/06 01:55:20 Done.
577 if (unsupport_cnt > 0)
578 return ScreenAvailability::UNSUPPORTED;
579 if (available_cnt > 0)
mark a. foltz 2017/01/03 21:47:13 This case should go first: if any URL is available
zhaobin 2017/01/06 01:55:20 Done.
580 return ScreenAvailability::AVAILABLE;
581
582 DCHECK(unavailable_cnt == urls.size());
mlamouri (slow - plz ping) 2017/01/04 16:15:00 DCHECK_EQ
zhaobin 2017/01/06 01:55:20 Done.
583 return ScreenAvailability::UNAVAILABLE;
mark a. foltz 2017/01/03 21:47:13 This case should go third, when some URLs are unav
zhaobin 2017/01/06 01:55:20 Done.
584 }
585
505 PresentationDispatcher::SendMessageRequest::SendMessageRequest( 586 PresentationDispatcher::SendMessageRequest::SendMessageRequest(
506 blink::mojom::PresentationSessionInfoPtr session_info, 587 blink::mojom::PresentationSessionInfoPtr session_info,
507 blink::mojom::ConnectionMessagePtr message) 588 blink::mojom::ConnectionMessagePtr message)
508 : session_info(std::move(session_info)), message(std::move(message)) {} 589 : session_info(std::move(session_info)), message(std::move(message)) {}
509 590
510 PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {} 591 PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {}
511 592
512 // static 593 // static
513 PresentationDispatcher::SendMessageRequest* 594 PresentationDispatcher::SendMessageRequest*
514 PresentationDispatcher::CreateSendTextMessageRequest( 595 PresentationDispatcher::CreateSendTextMessageRequest(
(...skipping 27 matching lines...) Expand all
542 session_info->id = presentationId.utf8(); 623 session_info->id = presentationId.utf8();
543 624
544 blink::mojom::ConnectionMessagePtr session_message = 625 blink::mojom::ConnectionMessagePtr session_message =
545 blink::mojom::ConnectionMessage::New(); 626 blink::mojom::ConnectionMessage::New();
546 session_message->type = type; 627 session_message->type = type;
547 session_message->data = std::vector<uint8_t>(data, data + length); 628 session_message->data = std::vector<uint8_t>(data, data + length);
548 return new SendMessageRequest(std::move(session_info), 629 return new SendMessageRequest(std::move(session_info),
549 std::move(session_message)); 630 std::move(session_message));
550 } 631 }
551 632
633 PresentationDispatcher::AvailabilityCallback::AvailabilityCallback(
634 const blink::WebVector<blink::WebURL>& availability_urls,
635 std::unique_ptr<blink::WebPresentationAvailabilityCallbacks>
636 availability_callback)
637 : urls(availability_urls), callback(std::move(availability_callback)) {}
638
639 PresentationDispatcher::AvailabilityCallback::~AvailabilityCallback() {}
640
552 PresentationDispatcher::AvailabilityStatus::AvailabilityStatus( 641 PresentationDispatcher::AvailabilityStatus::AvailabilityStatus(
553 const GURL& availability_url) 642 const GURL& availability_url)
554 : url(availability_url), 643 : url(availability_url),
555 last_known_availability(false), 644 last_known_availability(ScreenAvailability::UNKNOWN),
556 listening_state(ListeningState::INACTIVE) {} 645 listening_state(ListeningState::INACTIVE) {}
557 646
558 PresentationDispatcher::AvailabilityStatus::~AvailabilityStatus() { 647 PresentationDispatcher::AvailabilityStatus::~AvailabilityStatus() {
559 } 648 }
560 649
561 } // namespace content 650 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698