| Index: content/browser/presentation/presentation_service_impl.cc
|
| diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
|
| index e2b07132371e962bd60a77e06b82dac7c6a8866c..bb5d8ef56412b84c1047b74860efd353a75d2161 100644
|
| --- a/content/browser/presentation/presentation_service_impl.cc
|
| +++ b/content/browser/presentation/presentation_service_impl.cc
|
| @@ -4,6 +4,8 @@
|
|
|
| #include "content/browser/presentation/presentation_service_impl.h"
|
|
|
| +#include <algorithm>
|
| +
|
| #include "base/logging.h"
|
| #include "content/browser/presentation/presentation_type_converters.h"
|
| #include "content/public/browser/content_browser_client.h"
|
| @@ -86,13 +88,17 @@ void PresentationServiceImpl::GetScreenAvailability(
|
| const mojo::String& presentation_url,
|
| const ScreenAvailabilityMojoCallback& callback) {
|
| DVLOG(2) << "GetScreenAvailability";
|
| - if (!delegate_)
|
| + if (!delegate_) {
|
| + callback.Run(presentation_url, false);
|
| return;
|
| + }
|
|
|
| ScreenAvailabilityContext* context =
|
| GetOrCreateAvailabilityContext(presentation_url.get());
|
| - if (!context)
|
| + if (!context) {
|
| + callback.Run(presentation_url, false);
|
| return;
|
| + }
|
| context->CallbackReceived(callback);
|
| }
|
|
|
| @@ -111,6 +117,8 @@ void PresentationServiceImpl::OnScreenAvailabilityListenerRemoved(
|
| render_frame_host_->GetProcess()->GetID(),
|
| render_frame_host_->GetRoutingID(),
|
| it->second.get());
|
| + // Resolve the context's pending callbacks before removing it.
|
| + it->second->OnScreenAvailabilityChanged(false);
|
| availability_contexts_.erase(it);
|
| }
|
|
|
| @@ -124,8 +132,13 @@ void PresentationServiceImpl::StartSession(
|
| const mojo::String& presentation_id,
|
| const NewSessionMojoCallback& callback) {
|
| DVLOG(2) << "StartSession";
|
| - if (!delegate_)
|
| + if (!delegate_) {
|
| + callback.Run(
|
| + presentation::PresentationSessionInfoPtr(),
|
| + presentation::PresentationError::From(
|
| + PresentationError(PRESENTATION_ERROR_UNKNOWN, "")));
|
| return;
|
| + }
|
|
|
| queued_start_session_requests_.push_back(make_linked_ptr(
|
| new StartSessionRequest(presentation_url, presentation_id, callback)));
|
| @@ -138,14 +151,20 @@ void PresentationServiceImpl::JoinSession(
|
| const mojo::String& presentation_id,
|
| const NewSessionMojoCallback& callback) {
|
| DVLOG(2) << "JoinSession";
|
| - if (!delegate_)
|
| + if (!delegate_) {
|
| + callback.Run(
|
| + presentation::PresentationSessionInfoPtr(),
|
| + presentation::PresentationError::From(
|
| + PresentationError(PRESENTATION_ERROR_UNKNOWN, "")));
|
| return;
|
| + }
|
|
|
| delegate_->JoinSession(
|
| render_frame_host_->GetProcess()->GetID(),
|
| render_frame_host_->GetRoutingID(),
|
| presentation_url,
|
| presentation_id,
|
| + // TODO(imcheng): These callbacks may be dropped. http://crbug.com/468575
|
| base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded,
|
| weak_factory_.GetWeakPtr(), false, callback),
|
| base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError,
|
| @@ -173,6 +192,7 @@ void PresentationServiceImpl::DoStartSession(
|
| render_frame_host_->GetRoutingID(),
|
| presentation_url,
|
| presentation_id,
|
| + // TODO(imcheng): These callbacks may be dropped. http://crbug.com/468575
|
| base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded,
|
| weak_factory_.GetWeakPtr(), true, callback),
|
| base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionError,
|
| @@ -238,14 +258,12 @@ void PresentationServiceImpl::SetDefaultPresentationURL(
|
| }
|
|
|
| // Have already started listening. Create a listener for the new URL and
|
| - // transfer the callback from the old listener, if any.
|
| + // transfer the callbacks from the old listener, if any.
|
| // This is done so that a listener added before default URL is changed
|
| // will continue to work.
|
| - ScreenAvailabilityMojoCallback* old_callback = old_it->second->GetCallback();
|
| ScreenAvailabilityContext* context =
|
| GetOrCreateAvailabilityContext(new_default_url);
|
| - if (old_callback)
|
| - context->CallbackReceived(*old_callback);
|
| + old_it->second->PassPendingCallbacks(context);
|
|
|
| // Remove listener for old default presentation URL.
|
| delegate_->RemoveScreenAvailabilityListener(
|
| @@ -303,7 +321,11 @@ void PresentationServiceImpl::Reset() {
|
|
|
| default_presentation_url_.clear();
|
| default_presentation_id_.clear();
|
| + for (const auto& context : availability_contexts_) {
|
| + context.second->OnScreenAvailabilityChanged(false);
|
| + }
|
| availability_contexts_.clear();
|
| + // TODO(imcheng): This may drop callbacks. See http://crbug.com/468575.
|
| queued_start_session_requests_.clear();
|
| }
|
|
|
| @@ -327,21 +349,16 @@ void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived(
|
| // NOTE: This will overwrite previously registered callback if any.
|
| if (!available_ptr_) {
|
| // No results yet, store callback for later invocation.
|
| - callback_ptr_.reset(new ScreenAvailabilityMojoCallback(callback));
|
| + callbacks_.push_back(new ScreenAvailabilityMojoCallback(callback));
|
| } else {
|
| // Run callback now, reset result.
|
| // There shouldn't be any callbacks stored in this scenario.
|
| - DCHECK(!callback_ptr_);
|
| + DCHECK(!HasPendingCallbacks());
|
| callback.Run(presentation_url_, *available_ptr_);
|
| - Reset();
|
| + available_ptr_.reset();
|
| }
|
| }
|
|
|
| -void PresentationServiceImpl::ScreenAvailabilityContext::Reset() {
|
| - callback_ptr_.reset();
|
| - available_ptr_.reset();
|
| -}
|
| -
|
| std::string PresentationServiceImpl::ScreenAvailabilityContext
|
| ::GetPresentationUrl() const {
|
| return presentation_url_;
|
| @@ -349,21 +366,32 @@ std::string PresentationServiceImpl::ScreenAvailabilityContext
|
|
|
| void PresentationServiceImpl::ScreenAvailabilityContext
|
| ::OnScreenAvailabilityChanged(bool available) {
|
| - if (!callback_ptr_) {
|
| + if (!HasPendingCallbacks()) {
|
| // No callback, stash the result for now.
|
| available_ptr_.reset(new bool(available));
|
| } else {
|
| - // Invoke callback and erase it.
|
| + // Invoke callbacks and erase them.
|
| // There shouldn't be any result stored in this scenario.
|
| DCHECK(!available_ptr_);
|
| - callback_ptr_->Run(presentation_url_, available);
|
| - Reset();
|
| + ScopedVector<ScreenAvailabilityMojoCallback> callbacks;
|
| + callbacks.swap(callbacks_);
|
| + for (const auto& callback : callbacks)
|
| + callback->Run(presentation_url_, available);
|
| }
|
| }
|
|
|
| -PresentationServiceImpl::ScreenAvailabilityMojoCallback*
|
| -PresentationServiceImpl::ScreenAvailabilityContext::GetCallback() const {
|
| - return callback_ptr_.get();
|
| +void PresentationServiceImpl::ScreenAvailabilityContext
|
| + ::PassPendingCallbacks(
|
| + PresentationServiceImpl::ScreenAvailabilityContext* other) {
|
| + std::vector<ScreenAvailabilityMojoCallback*> callbacks;
|
| + callbacks_.release(&callbacks);
|
| + std::copy(callbacks.begin(), callbacks.end(),
|
| + std::back_inserter(other->callbacks_));
|
| +}
|
| +
|
| +bool PresentationServiceImpl::ScreenAvailabilityContext
|
| + ::HasPendingCallbacks() const {
|
| + return !callbacks_.empty();
|
| }
|
|
|
| PresentationServiceImpl::StartSessionRequest::StartSessionRequest(
|
| @@ -379,3 +407,4 @@ PresentationServiceImpl::StartSessionRequest::~StartSessionRequest() {
|
| }
|
|
|
| } // namespace content
|
| +
|
|
|