Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |