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

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

Issue 2598063002: [Presentation API] Handle multiple Presentation URLs in PresentationRequest::getAvailability() (Closed)
Patch Set: Created 3 years, 12 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 78
79 constexpr char k_not_supported_error[] =
80 "getAvailability() isn't supported at the moment. It can be due to "
mark a. foltz 2016/12/23 01:04:22 kNotSupportedError per style guide
zhaobin 2016/12/29 18:48:38 Code removed.
81 "a permanent or temporary system limitation. It is recommended to "
82 "try to blindly start a session in that case.";
mark a. foltz 2016/12/23 01:04:22 I would keep this simple: Screen availability mo
zhaobin 2016/12/29 18:48:38 Code removed.
79 } // namespace 83 } // namespace
80 84
81 namespace content { 85 namespace content {
82 86
83 PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame) 87 PresentationDispatcher::PresentationDispatcher(RenderFrame* render_frame)
84 : RenderFrameObserver(render_frame), 88 : RenderFrameObserver(render_frame),
85 controller_(nullptr), 89 controller_(nullptr),
86 binding_(this) { 90 binding_(this) {
87 } 91 }
88 92
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 void PresentationDispatcher::terminateSession( 243 void PresentationDispatcher::terminateSession(
240 const blink::WebURL& presentationUrl, 244 const blink::WebURL& presentationUrl,
241 const blink::WebString& presentationId) { 245 const blink::WebString& presentationId) {
242 ConnectToPresentationServiceIfNeeded(); 246 ConnectToPresentationServiceIfNeeded();
243 presentation_service_->Terminate(presentationUrl, presentationId.utf8()); 247 presentation_service_->Terminate(presentationUrl, presentationId.utf8());
244 } 248 }
245 249
246 void PresentationDispatcher::getAvailability( 250 void PresentationDispatcher::getAvailability(
247 const blink::WebVector<blink::WebURL>& availabilityUrls, 251 const blink::WebVector<blink::WebURL>& availabilityUrls,
248 std::unique_ptr<blink::WebPresentationAvailabilityCallbacks> callbacks) { 252 std::unique_ptr<blink::WebPresentationAvailabilityCallbacks> callbacks) {
249 // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. 253 std::vector<GURL> urls;
250 const blink::WebURL& availabilityUrl = availabilityUrls[0]; 254 for (const auto& url : availabilityUrls)
255 urls.push_back(url);
256
251 AvailabilityStatus* status = nullptr; 257 AvailabilityStatus* status = nullptr;
252 auto status_it = availability_status_.find(availabilityUrl); 258 auto status_it = availability_status_.find(urls);
253 if (status_it == availability_status_.end()) { 259 if (status_it == availability_status_.end()) {
254 status = new AvailabilityStatus(availabilityUrl); 260 status = new AvailabilityStatus(urls);
255 availability_status_[availabilityUrl] = base::WrapUnique(status); 261 availability_status_[urls] = base::WrapUnique(status);
mark a. foltz 2016/12/23 01:04:22 Would it be simpler to continue tracking status fo
zhaobin 2016/12/29 18:48:38 Done.
256 } else { 262 } else {
257 status = status_it->second.get(); 263 status = status_it->second.get();
258 } 264 }
259 DCHECK(status); 265 DCHECK(status);
260 266
261 if (status->listening_state == ListeningState::ACTIVE) { 267 auto presentation_error = blink::WebPresentationError(
262 base::ThreadTaskRunnerHandle::Get()->PostTask( 268 blink::WebPresentationError::ErrorTypeAvailabilityNotSupported,
263 FROM_HERE, 269 blink::WebString::fromUTF8(k_not_supported_error));
264 base::Bind(&blink::WebPresentationAvailabilityCallbacks::onSuccess, 270
265 base::Passed(&callbacks), status->last_known_availability)); 271 auto request_availability = GetRequestAvailability(urls);
266 return; 272
273 switch (request_availability) {
274 case ScreenAvailability::UNKNOWN:
275 status->availability_callbacks.Add(std::move(callbacks));
276 UpdateListeningState(status);
277 break;
278 case ScreenAvailability::UNSUPPORTED:
279 base::ThreadTaskRunnerHandle::Get()->PostTask(
280 FROM_HERE,
281 base::Bind(&blink::WebPresentationAvailabilityCallbacks::onError,
282 base::Passed(&callbacks), presentation_error));
283 break;
284 case ScreenAvailability::AVAILABLE:
285 case ScreenAvailability::UNAVAILABLE:
286 bool is_available = request_availability == ScreenAvailability::AVAILABLE;
287 base::ThreadTaskRunnerHandle::Get()->PostTask(
288 FROM_HERE,
289 base::Bind(&blink::WebPresentationAvailabilityCallbacks::onSuccess,
290 base::Passed(&callbacks), is_available));
291 break;
267 } 292 }
268
269 status->availability_callbacks.Add(std::move(callbacks));
270 UpdateListeningState(status);
271 } 293 }
272 294
273 void PresentationDispatcher::startListening( 295 void PresentationDispatcher::startListening(
274 blink::WebPresentationAvailabilityObserver* observer) { 296 blink::WebPresentationAvailabilityObserver* observer) {
275 // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. 297 std::vector<GURL> urls;
276 const blink::WebURL& availabilityUrl = observer->urls()[0]; 298 for (const auto& url : observer->urls())
277 auto status_it = availability_status_.find(availabilityUrl); 299 urls.push_back(url);
300
301 auto status_it = availability_status_.find(urls);
278 if (status_it == availability_status_.end()) { 302 if (status_it == availability_status_.end()) {
279 DLOG(WARNING) << "Start listening for availability for unknown URL " 303 DLOG(WARNING) << "Start listening for availability for unknown URLs:";
280 << GURL(availabilityUrl); 304 for (const auto& url : urls)
305 DLOG(WARNING) << " " << url;
281 return; 306 return;
282 } 307 }
283 status_it->second->availability_observers.insert(observer); 308 status_it->second->availability_observers.insert(observer);
284 UpdateListeningState(status_it->second.get()); 309 UpdateListeningState(status_it->second.get());
285 } 310 }
286 311
287 void PresentationDispatcher::stopListening( 312 void PresentationDispatcher::stopListening(
288 blink::WebPresentationAvailabilityObserver* observer) { 313 blink::WebPresentationAvailabilityObserver* observer) {
289 // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. 314 std::vector<GURL> urls;
290 const blink::WebURL& availabilityUrl = observer->urls()[0]; 315 for (const auto& url : observer->urls())
291 auto status_it = availability_status_.find(availabilityUrl); 316 urls.push_back(url);
317
318 auto status_it = availability_status_.find(urls);
292 if (status_it == availability_status_.end()) { 319 if (status_it == availability_status_.end()) {
293 DLOG(WARNING) << "Stop listening for availability for unknown URL " 320 DLOG(WARNING) << "Stop listening for availability for unknown URLs: ";
294 << GURL(availabilityUrl); 321 for (const auto& url : urls)
322 DLOG(WARNING) << " " << url;
295 return; 323 return;
296 } 324 }
297 status_it->second->availability_observers.erase(observer); 325 status_it->second->availability_observers.erase(observer);
298 UpdateListeningState(status_it->second.get()); 326 UpdateListeningState(status_it->second.get());
299 } 327 }
300 328
301 void PresentationDispatcher::setDefaultPresentationUrls( 329 void PresentationDispatcher::setDefaultPresentationUrls(
302 const blink::WebVector<blink::WebURL>& presentationUrls) { 330 const blink::WebVector<blink::WebURL>& presentationUrls) {
303 ConnectToPresentationServiceIfNeeded(); 331 ConnectToPresentationServiceIfNeeded();
304 332
(...skipping 22 matching lines...) Expand all
327 MessageRequestQueue empty; 355 MessageRequestQueue empty;
328 std::swap(message_request_queue_, empty); 356 std::swap(message_request_queue_, empty);
329 } 357 }
330 358
331 void PresentationDispatcher::OnDestruct() { 359 void PresentationDispatcher::OnDestruct() {
332 delete this; 360 delete this;
333 } 361 }
334 362
335 void PresentationDispatcher::OnScreenAvailabilityUpdated(const GURL& url, 363 void PresentationDispatcher::OnScreenAvailabilityUpdated(const GURL& url,
336 bool available) { 364 bool available) {
337 auto status_it = availability_status_.find(url); 365 OnScreenAvailabilityUpdated(url, available ? ScreenAvailability::AVAILABLE
338 if (status_it == availability_status_.end()) 366 : ScreenAvailability::UNAVAILABLE);
339 return; 367 }
340 AvailabilityStatus* status = status_it->second.get(); 368
369 void PresentationDispatcher::OnScreenAvailabilityNotSupported(const GURL& url) {
370 OnScreenAvailabilityUpdated(url, ScreenAvailability::UNSUPPORTED);
371 }
372
373 void PresentationDispatcher::OnScreenAvailabilityUpdated(
374 const GURL& url,
375 ScreenAvailability screen_availability) {
376 DCHECK(base::ContainsKey(url_listening_state_, url));
377
378 if (url_listening_state_[url] == ListeningState::WAITING)
379 url_listening_state_[url] = ListeningState::ACTIVE;
380
381 screen_availability_[url] = screen_availability;
382
383 for (auto& status_it : availability_status_) {
384 if (!base::ContainsValue(status_it.first, url))
385 continue;
386
387 auto request_availability = GetRequestAvailability(status_it.first);
388 switch (request_availability) {
389 case ScreenAvailability::UNKNOWN:
390 break;
391 case ScreenAvailability::UNSUPPORTED:
392 OnScreenAvailabilityNotSupported(status_it.second.get());
393 break;
394 case ScreenAvailability::AVAILABLE:
395 case ScreenAvailability::UNAVAILABLE:
396 OnScreenAvailabilityUpdated(
397 status_it.second.get(),
398 (request_availability == ScreenAvailability::AVAILABLE));
399 break;
400 }
401 }
402 }
403
404 void PresentationDispatcher::OnScreenAvailabilityUpdated(
405 AvailabilityStatus* status,
406 bool available) {
341 DCHECK(status); 407 DCHECK(status);
342 408
343 if (status->listening_state == ListeningState::WAITING)
344 status->listening_state = ListeningState::ACTIVE;
345
346 for (auto* observer : status->availability_observers) 409 for (auto* observer : status->availability_observers)
347 observer->availabilityChanged(available); 410 observer->availabilityChanged(available);
348 411
349 for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks); 412 for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks);
350 !iter.IsAtEnd(); iter.Advance()) { 413 !iter.IsAtEnd(); iter.Advance())
351 iter.GetCurrentValue()->onSuccess(available); 414 iter.GetCurrentValue()->onSuccess(available);
352 } 415
353 status->last_known_availability = available;
354 status->availability_callbacks.Clear(); 416 status->availability_callbacks.Clear();
355 UpdateListeningState(status); 417 UpdateListeningState(status);
356 } 418 }
357 419
358 void PresentationDispatcher::OnScreenAvailabilityNotSupported(const GURL& url) { 420 void PresentationDispatcher::OnScreenAvailabilityNotSupported(
359 auto status_it = availability_status_.find(url); 421 AvailabilityStatus* status) {
360 if (status_it == availability_status_.end())
361 return;
362 AvailabilityStatus* status = status_it->second.get();
363 DCHECK(status); 422 DCHECK(status);
364 DCHECK(status->listening_state == ListeningState::WAITING);
365 423
366 const blink::WebString& not_supported_error = blink::WebString::fromUTF8(
367 "getAvailability() isn't supported at the moment. It can be due to "
368 "a permanent or temporary system limitation. It is recommended to "
369 "try to blindly start a session in that case.");
370 for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks); 424 for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks);
371 !iter.IsAtEnd(); iter.Advance()) { 425 !iter.IsAtEnd(); iter.Advance()) {
372 iter.GetCurrentValue()->onError(blink::WebPresentationError( 426 iter.GetCurrentValue()->onError(blink::WebPresentationError(
373 blink::WebPresentationError::ErrorTypeAvailabilityNotSupported, 427 blink::WebPresentationError::ErrorTypeAvailabilityNotSupported,
374 not_supported_error)); 428 blink::WebString::fromUTF8(k_not_supported_error)));
375 } 429 }
376 status->availability_callbacks.Clear(); 430 status->availability_callbacks.Clear();
377 UpdateListeningState(status); 431 UpdateListeningState(status);
378 } 432 }
379 433
380 void PresentationDispatcher::OnDefaultSessionStarted( 434 void PresentationDispatcher::OnDefaultSessionStarted(
381 blink::mojom::PresentationSessionInfoPtr session_info) { 435 blink::mojom::PresentationSessionInfoPtr session_info) {
382 if (!controller_) 436 if (!controller_)
383 return; 437 return;
384 438
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 } 531 }
478 532
479 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() { 533 void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
480 if (presentation_service_.get()) 534 if (presentation_service_.get())
481 return; 535 return;
482 536
483 render_frame()->GetRemoteInterfaces()->GetInterface(&presentation_service_); 537 render_frame()->GetRemoteInterfaces()->GetInterface(&presentation_service_);
484 presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind()); 538 presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind());
485 } 539 }
486 540
541 void PresentationDispatcher::SetPresentationServiceForTest(
542 blink::mojom::PresentationServicePtr presentation_service) {
543 presentation_service_ = std::move(presentation_service);
544 }
545
487 void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) { 546 void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) {
488 bool should_listen = !status->availability_callbacks.IsEmpty() || 547 // Calculate if we should listen to status->urls.
489 !status->availability_observers.empty(); 548 std::map<GURL, bool> url_should_listen;
490 bool is_listening = status->listening_state != ListeningState::INACTIVE; 549 for (const auto& it : availability_status_) {
550 bool should_listen = !it.second->availability_callbacks.IsEmpty() ||
551 !it.second->availability_observers.empty();
491 552
492 if (should_listen == is_listening) 553 for (const auto& url : it.first) {
493 return; 554 if (base::ContainsValue(status->urls, url))
555 url_should_listen[url] = url_should_listen[url] || should_listen;
556 }
557 }
494 558
495 ConnectToPresentationServiceIfNeeded(); 559 ConnectToPresentationServiceIfNeeded();
496 if (should_listen) { 560
497 status->listening_state = ListeningState::WAITING; 561 for (const auto& url : status->urls) {
498 presentation_service_->ListenForScreenAvailability(status->url); 562 bool is_listening = false;
499 } else { 563 if (base::ContainsKey(url_listening_state_, url))
500 status->listening_state = ListeningState::INACTIVE; 564 is_listening = url_listening_state_[url] != ListeningState::INACTIVE;
501 presentation_service_->StopListeningForScreenAvailability(status->url); 565
566 bool should_listen = url_should_listen[url];
567
568 if (should_listen == is_listening)
569 continue;
570
571 if (should_listen) {
572 url_listening_state_[url] = ListeningState::WAITING;
573 presentation_service_->ListenForScreenAvailability(url);
574 } else {
575 url_listening_state_[url] = ListeningState::INACTIVE;
576 presentation_service_->StopListeningForScreenAvailability(url);
577 }
502 } 578 }
503 } 579 }
504 580
581 PresentationDispatcher::ScreenAvailability
582 PresentationDispatcher::GetRequestAvailability(const std::vector<GURL>& urls) {
583 size_t available_cnt = 0;
584 size_t unavailable_cnt = 0;
585 size_t unsupport_cnt = 0;
586
587 for (const auto& url : urls) {
588 if (!base::ContainsKey(screen_availability_, url))
589 return ScreenAvailability::UNKNOWN;
590
591 auto url_availability = screen_availability_[url];
592 switch (url_availability) {
593 case ScreenAvailability::AVAILABLE:
594 available_cnt++;
595 break;
596 case ScreenAvailability::UNAVAILABLE:
597 unavailable_cnt++;
598 break;
599 case ScreenAvailability::UNSUPPORTED:
600 unsupport_cnt++;
601 break;
602 case ScreenAvailability::UNKNOWN:
603 break;
604 }
605 }
606
607 if (available_cnt > 0)
608 return ScreenAvailability::AVAILABLE;
609 if (unavailable_cnt > 0)
610 return ScreenAvailability::UNAVAILABLE;
611
612 DCHECK(unsupport_cnt == urls.size());
613 return ScreenAvailability::UNSUPPORTED;
614 }
615
505 PresentationDispatcher::SendMessageRequest::SendMessageRequest( 616 PresentationDispatcher::SendMessageRequest::SendMessageRequest(
506 blink::mojom::PresentationSessionInfoPtr session_info, 617 blink::mojom::PresentationSessionInfoPtr session_info,
507 blink::mojom::ConnectionMessagePtr message) 618 blink::mojom::ConnectionMessagePtr message)
508 : session_info(std::move(session_info)), message(std::move(message)) {} 619 : session_info(std::move(session_info)), message(std::move(message)) {}
509 620
510 PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {} 621 PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {}
511 622
512 // static 623 // static
513 PresentationDispatcher::SendMessageRequest* 624 PresentationDispatcher::SendMessageRequest*
514 PresentationDispatcher::CreateSendTextMessageRequest( 625 PresentationDispatcher::CreateSendTextMessageRequest(
(...skipping 28 matching lines...) Expand all
543 654
544 blink::mojom::ConnectionMessagePtr session_message = 655 blink::mojom::ConnectionMessagePtr session_message =
545 blink::mojom::ConnectionMessage::New(); 656 blink::mojom::ConnectionMessage::New();
546 session_message->type = type; 657 session_message->type = type;
547 session_message->data = std::vector<uint8_t>(data, data + length); 658 session_message->data = std::vector<uint8_t>(data, data + length);
548 return new SendMessageRequest(std::move(session_info), 659 return new SendMessageRequest(std::move(session_info),
549 std::move(session_message)); 660 std::move(session_message));
550 } 661 }
551 662
552 PresentationDispatcher::AvailabilityStatus::AvailabilityStatus( 663 PresentationDispatcher::AvailabilityStatus::AvailabilityStatus(
553 const GURL& availability_url) 664 const std::vector<GURL>& availability_urls)
554 : url(availability_url), 665 : urls(availability_urls) {}
555 last_known_availability(false),
556 listening_state(ListeningState::INACTIVE) {}
557 666
558 PresentationDispatcher::AvailabilityStatus::~AvailabilityStatus() { 667 PresentationDispatcher::AvailabilityStatus::~AvailabilityStatus() {
559 } 668 }
560 669
561 } // namespace content 670 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698