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..1add8939bd053bd37fc9e7f2bb1cca163738fcf1 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);; |
imcheng
2015/03/19 01:21:14
extra semicolon
Ken Rockot(use gerrit already)
2015/03/19 16:16:39
Done.
|
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,8 +151,13 @@ 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(), |
@@ -238,14 +256,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( |
@@ -327,21 +343,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 +360,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 +401,4 @@ PresentationServiceImpl::StartSessionRequest::~StartSessionRequest() { |
} |
} // namespace content |
+ |