Chromium Code Reviews| Index: content/renderer/presentation/presentation_dispatcher.cc |
| diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc |
| index d11943b79e404df99222a41641dd1e3910598231..ea70082b0746a3409dbe3fb8fd43d9706dce5fa6 100644 |
| --- a/content/renderer/presentation/presentation_dispatcher.cc |
| +++ b/content/renderer/presentation/presentation_dispatcher.cc |
| @@ -76,6 +76,10 @@ GetWebPresentationConnectionCloseReasonFromMojo( |
| } |
| } |
| +constexpr char k_not_supported_error[] = |
| + "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.
|
| + "a permanent or temporary system limitation. It is recommended to " |
| + "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.
|
| } // namespace |
| namespace content { |
| @@ -246,38 +250,59 @@ void PresentationDispatcher::terminateSession( |
| void PresentationDispatcher::getAvailability( |
| const blink::WebVector<blink::WebURL>& availabilityUrls, |
| std::unique_ptr<blink::WebPresentationAvailabilityCallbacks> callbacks) { |
| - // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. |
| - const blink::WebURL& availabilityUrl = availabilityUrls[0]; |
| + std::vector<GURL> urls; |
| + for (const auto& url : availabilityUrls) |
| + urls.push_back(url); |
| + |
| AvailabilityStatus* status = nullptr; |
| - auto status_it = availability_status_.find(availabilityUrl); |
| + auto status_it = availability_status_.find(urls); |
| if (status_it == availability_status_.end()) { |
| - status = new AvailabilityStatus(availabilityUrl); |
| - availability_status_[availabilityUrl] = base::WrapUnique(status); |
| + status = new AvailabilityStatus(urls); |
| + 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.
|
| } else { |
| status = status_it->second.get(); |
| } |
| DCHECK(status); |
| - if (status->listening_state == ListeningState::ACTIVE) { |
| - base::ThreadTaskRunnerHandle::Get()->PostTask( |
| - FROM_HERE, |
| - base::Bind(&blink::WebPresentationAvailabilityCallbacks::onSuccess, |
| - base::Passed(&callbacks), status->last_known_availability)); |
| - return; |
| + auto presentation_error = blink::WebPresentationError( |
| + blink::WebPresentationError::ErrorTypeAvailabilityNotSupported, |
| + blink::WebString::fromUTF8(k_not_supported_error)); |
| + |
| + auto request_availability = GetRequestAvailability(urls); |
| + |
| + switch (request_availability) { |
| + case ScreenAvailability::UNKNOWN: |
| + status->availability_callbacks.Add(std::move(callbacks)); |
| + UpdateListeningState(status); |
| + break; |
| + case ScreenAvailability::UNSUPPORTED: |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&blink::WebPresentationAvailabilityCallbacks::onError, |
| + base::Passed(&callbacks), presentation_error)); |
| + break; |
| + case ScreenAvailability::AVAILABLE: |
| + case ScreenAvailability::UNAVAILABLE: |
| + bool is_available = request_availability == ScreenAvailability::AVAILABLE; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&blink::WebPresentationAvailabilityCallbacks::onSuccess, |
| + base::Passed(&callbacks), is_available)); |
| + break; |
| } |
| - |
| - status->availability_callbacks.Add(std::move(callbacks)); |
| - UpdateListeningState(status); |
| } |
| void PresentationDispatcher::startListening( |
| blink::WebPresentationAvailabilityObserver* observer) { |
| - // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. |
| - const blink::WebURL& availabilityUrl = observer->urls()[0]; |
| - auto status_it = availability_status_.find(availabilityUrl); |
| + std::vector<GURL> urls; |
| + for (const auto& url : observer->urls()) |
| + urls.push_back(url); |
| + |
| + auto status_it = availability_status_.find(urls); |
| if (status_it == availability_status_.end()) { |
| - DLOG(WARNING) << "Start listening for availability for unknown URL " |
| - << GURL(availabilityUrl); |
| + DLOG(WARNING) << "Start listening for availability for unknown URLs:"; |
| + for (const auto& url : urls) |
| + DLOG(WARNING) << " " << url; |
| return; |
| } |
| status_it->second->availability_observers.insert(observer); |
| @@ -286,12 +311,15 @@ void PresentationDispatcher::startListening( |
| void PresentationDispatcher::stopListening( |
| blink::WebPresentationAvailabilityObserver* observer) { |
| - // TODO(mfoltz): Pass all URLs to PresentationService. See crbug.com/627655. |
| - const blink::WebURL& availabilityUrl = observer->urls()[0]; |
| - auto status_it = availability_status_.find(availabilityUrl); |
| + std::vector<GURL> urls; |
| + for (const auto& url : observer->urls()) |
| + urls.push_back(url); |
| + |
| + auto status_it = availability_status_.find(urls); |
| if (status_it == availability_status_.end()) { |
| - DLOG(WARNING) << "Stop listening for availability for unknown URL " |
| - << GURL(availabilityUrl); |
| + DLOG(WARNING) << "Stop listening for availability for unknown URLs: "; |
| + for (const auto& url : urls) |
| + DLOG(WARNING) << " " << url; |
| return; |
| } |
| status_it->second->availability_observers.erase(observer); |
| @@ -334,44 +362,70 @@ void PresentationDispatcher::OnDestruct() { |
| void PresentationDispatcher::OnScreenAvailabilityUpdated(const GURL& url, |
| bool available) { |
| - auto status_it = availability_status_.find(url); |
| - if (status_it == availability_status_.end()) |
| - return; |
| - AvailabilityStatus* status = status_it->second.get(); |
| - DCHECK(status); |
| + OnScreenAvailabilityUpdated(url, available ? ScreenAvailability::AVAILABLE |
| + : ScreenAvailability::UNAVAILABLE); |
| +} |
| - if (status->listening_state == ListeningState::WAITING) |
| - status->listening_state = ListeningState::ACTIVE; |
| +void PresentationDispatcher::OnScreenAvailabilityNotSupported(const GURL& url) { |
| + OnScreenAvailabilityUpdated(url, ScreenAvailability::UNSUPPORTED); |
| +} |
| + |
| +void PresentationDispatcher::OnScreenAvailabilityUpdated( |
| + const GURL& url, |
| + ScreenAvailability screen_availability) { |
| + DCHECK(base::ContainsKey(url_listening_state_, url)); |
| + |
| + if (url_listening_state_[url] == ListeningState::WAITING) |
| + url_listening_state_[url] = ListeningState::ACTIVE; |
| + |
| + screen_availability_[url] = screen_availability; |
| + |
| + for (auto& status_it : availability_status_) { |
| + if (!base::ContainsValue(status_it.first, url)) |
| + continue; |
| + |
| + auto request_availability = GetRequestAvailability(status_it.first); |
| + switch (request_availability) { |
| + case ScreenAvailability::UNKNOWN: |
| + break; |
| + case ScreenAvailability::UNSUPPORTED: |
| + OnScreenAvailabilityNotSupported(status_it.second.get()); |
| + break; |
| + case ScreenAvailability::AVAILABLE: |
| + case ScreenAvailability::UNAVAILABLE: |
| + OnScreenAvailabilityUpdated( |
| + status_it.second.get(), |
| + (request_availability == ScreenAvailability::AVAILABLE)); |
| + break; |
| + } |
| + } |
| +} |
| + |
| +void PresentationDispatcher::OnScreenAvailabilityUpdated( |
| + AvailabilityStatus* status, |
| + bool available) { |
| + DCHECK(status); |
| for (auto* observer : status->availability_observers) |
| observer->availabilityChanged(available); |
| for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks); |
| - !iter.IsAtEnd(); iter.Advance()) { |
| + !iter.IsAtEnd(); iter.Advance()) |
| iter.GetCurrentValue()->onSuccess(available); |
| - } |
| - status->last_known_availability = available; |
| + |
| status->availability_callbacks.Clear(); |
| UpdateListeningState(status); |
| } |
| -void PresentationDispatcher::OnScreenAvailabilityNotSupported(const GURL& url) { |
| - auto status_it = availability_status_.find(url); |
| - if (status_it == availability_status_.end()) |
| - return; |
| - AvailabilityStatus* status = status_it->second.get(); |
| +void PresentationDispatcher::OnScreenAvailabilityNotSupported( |
| + AvailabilityStatus* status) { |
| DCHECK(status); |
| - DCHECK(status->listening_state == ListeningState::WAITING); |
| - const blink::WebString& not_supported_error = blink::WebString::fromUTF8( |
| - "getAvailability() isn't supported at the moment. It can be due to " |
| - "a permanent or temporary system limitation. It is recommended to " |
| - "try to blindly start a session in that case."); |
| for (AvailabilityCallbacksMap::iterator iter(&status->availability_callbacks); |
| !iter.IsAtEnd(); iter.Advance()) { |
| iter.GetCurrentValue()->onError(blink::WebPresentationError( |
| blink::WebPresentationError::ErrorTypeAvailabilityNotSupported, |
| - not_supported_error)); |
| + blink::WebString::fromUTF8(k_not_supported_error))); |
| } |
| status->availability_callbacks.Clear(); |
| UpdateListeningState(status); |
| @@ -484,22 +538,79 @@ void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() { |
| presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind()); |
| } |
| -void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) { |
| - bool should_listen = !status->availability_callbacks.IsEmpty() || |
| - !status->availability_observers.empty(); |
| - bool is_listening = status->listening_state != ListeningState::INACTIVE; |
| +void PresentationDispatcher::SetPresentationServiceForTest( |
| + blink::mojom::PresentationServicePtr presentation_service) { |
| + presentation_service_ = std::move(presentation_service); |
| +} |
| - if (should_listen == is_listening) |
| - return; |
| +void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) { |
| + // Calculate if we should listen to status->urls. |
| + std::map<GURL, bool> url_should_listen; |
| + for (const auto& it : availability_status_) { |
| + bool should_listen = !it.second->availability_callbacks.IsEmpty() || |
| + !it.second->availability_observers.empty(); |
| + |
| + for (const auto& url : it.first) { |
| + if (base::ContainsValue(status->urls, url)) |
| + url_should_listen[url] = url_should_listen[url] || should_listen; |
| + } |
| + } |
| ConnectToPresentationServiceIfNeeded(); |
| - if (should_listen) { |
| - status->listening_state = ListeningState::WAITING; |
| - presentation_service_->ListenForScreenAvailability(status->url); |
| - } else { |
| - status->listening_state = ListeningState::INACTIVE; |
| - presentation_service_->StopListeningForScreenAvailability(status->url); |
| + |
| + for (const auto& url : status->urls) { |
| + bool is_listening = false; |
| + if (base::ContainsKey(url_listening_state_, url)) |
| + is_listening = url_listening_state_[url] != ListeningState::INACTIVE; |
| + |
| + bool should_listen = url_should_listen[url]; |
| + |
| + if (should_listen == is_listening) |
| + continue; |
| + |
| + if (should_listen) { |
| + url_listening_state_[url] = ListeningState::WAITING; |
| + presentation_service_->ListenForScreenAvailability(url); |
| + } else { |
| + url_listening_state_[url] = ListeningState::INACTIVE; |
| + presentation_service_->StopListeningForScreenAvailability(url); |
| + } |
| + } |
| +} |
| + |
| +PresentationDispatcher::ScreenAvailability |
| +PresentationDispatcher::GetRequestAvailability(const std::vector<GURL>& urls) { |
| + size_t available_cnt = 0; |
| + size_t unavailable_cnt = 0; |
| + size_t unsupport_cnt = 0; |
| + |
| + for (const auto& url : urls) { |
| + if (!base::ContainsKey(screen_availability_, url)) |
| + return ScreenAvailability::UNKNOWN; |
| + |
| + auto url_availability = screen_availability_[url]; |
| + switch (url_availability) { |
| + case ScreenAvailability::AVAILABLE: |
| + available_cnt++; |
| + break; |
| + case ScreenAvailability::UNAVAILABLE: |
| + unavailable_cnt++; |
| + break; |
| + case ScreenAvailability::UNSUPPORTED: |
| + unsupport_cnt++; |
| + break; |
| + case ScreenAvailability::UNKNOWN: |
| + break; |
| + } |
| } |
| + |
| + if (available_cnt > 0) |
| + return ScreenAvailability::AVAILABLE; |
| + if (unavailable_cnt > 0) |
| + return ScreenAvailability::UNAVAILABLE; |
| + |
| + DCHECK(unsupport_cnt == urls.size()); |
| + return ScreenAvailability::UNSUPPORTED; |
| } |
| PresentationDispatcher::SendMessageRequest::SendMessageRequest( |
| @@ -550,10 +661,8 @@ PresentationDispatcher::CreateSendBinaryMessageRequest( |
| } |
| PresentationDispatcher::AvailabilityStatus::AvailabilityStatus( |
| - const GURL& availability_url) |
| - : url(availability_url), |
| - last_known_availability(false), |
| - listening_state(ListeningState::INACTIVE) {} |
| + const std::vector<GURL>& availability_urls) |
| + : urls(availability_urls) {} |
| PresentationDispatcher::AvailabilityStatus::~AvailabilityStatus() { |
| } |