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/browser/presentation/presentation_service_impl.h" | 5 #include "content/browser/presentation/presentation_service_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "content/browser/presentation/presentation_type_converters.h" | 10 #include "content/browser/presentation/presentation_type_converters.h" |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 binding_.reset(new mojo::Binding<presentation::PresentationService>( | 131 binding_.reset(new mojo::Binding<presentation::PresentationService>( |
132 this, request.Pass())); | 132 this, request.Pass())); |
133 binding_->set_error_handler(this); | 133 binding_->set_error_handler(this); |
134 } | 134 } |
135 | 135 |
136 void PresentationServiceImpl::OnConnectionError() { | 136 void PresentationServiceImpl::OnConnectionError() { |
137 DVLOG(1) << "OnConnectionError"; | 137 DVLOG(1) << "OnConnectionError"; |
138 delete this; | 138 delete this; |
139 } | 139 } |
140 | 140 |
141 PresentationServiceImpl::ScreenAvailabilityContext* | 141 void PresentationServiceImpl::SetClient( |
142 PresentationServiceImpl::GetOrCreateAvailabilityContext( | 142 presentation::PresentationServiceClientPtr client) { |
143 const std::string& presentation_url) { | 143 DCHECK(!client_.get()); |
144 auto it = availability_contexts_.find(presentation_url); | 144 // TODO(imcheng): Set ErrorHandler to listen for errors. |
145 if (it == availability_contexts_.end()) { | 145 client_ = client.Pass(); |
146 linked_ptr<ScreenAvailabilityContext> context( | |
147 new ScreenAvailabilityContext(presentation_url)); | |
148 if (!delegate_->AddScreenAvailabilityListener( | |
149 render_process_id_, render_frame_id_, context.get())) { | |
150 DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request."; | |
151 return nullptr; | |
152 } | |
153 it = availability_contexts_.insert( | |
154 std::make_pair(context->GetPresentationUrl(), context)).first; | |
155 } | |
156 return it->second.get(); | |
157 } | 146 } |
158 | 147 |
159 void PresentationServiceImpl::ListenForScreenAvailability( | 148 void PresentationServiceImpl::ListenForScreenAvailability() { |
160 const mojo::String& presentation_url, | |
161 const ScreenAvailabilityMojoCallback& callback) { | |
162 DVLOG(2) << "ListenForScreenAvailability"; | 149 DVLOG(2) << "ListenForScreenAvailability"; |
163 if (!delegate_) { | 150 if (!delegate_) |
164 callback.Run(presentation_url, false); | 151 return; |
| 152 |
| 153 if (screen_availability_listener_.get() && |
| 154 screen_availability_listener_->GetPresentationUrl() == |
| 155 default_presentation_url_) { |
165 return; | 156 return; |
166 } | 157 } |
167 | 158 |
168 ScreenAvailabilityContext* context = | 159 ResetScreenAvailabilityListener(default_presentation_url_); |
169 GetOrCreateAvailabilityContext(presentation_url.get()); | |
170 if (!context) { | |
171 callback.Run(presentation_url, false); | |
172 return; | |
173 } | |
174 context->CallbackReceived(callback); | |
175 } | 160 } |
176 | 161 |
177 void PresentationServiceImpl::RemoveScreenAvailabilityListener( | 162 void PresentationServiceImpl::ResetScreenAvailabilityListener( |
178 const mojo::String& presentation_url) { | 163 const std::string& presentation_url) { |
179 DVLOG(2) << "RemoveScreenAvailabilityListener"; | 164 DCHECK(delegate_); |
| 165 DCHECK(!screen_availability_listener_.get() || |
| 166 presentation_url != default_presentation_url_); |
| 167 |
| 168 // (1) Unregister old listener with delegate |
| 169 StopListeningForScreenAvailability(); |
| 170 |
| 171 // (2) Replace old listener with new listener |
| 172 screen_availability_listener_.reset(new ScreenAvailabilityListenerImpl( |
| 173 presentation_url, this)); |
| 174 |
| 175 // (3) Register new listener with delegate |
| 176 if (!delegate_->AddScreenAvailabilityListener( |
| 177 render_process_id_, |
| 178 render_frame_id_, |
| 179 screen_availability_listener_.get())) { |
| 180 DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request."; |
| 181 screen_availability_listener_.reset(); |
| 182 } |
| 183 } |
| 184 |
| 185 void PresentationServiceImpl::StopListeningForScreenAvailability() { |
| 186 DVLOG(2) << "StopListeningForScreenAvailability"; |
180 if (!delegate_) | 187 if (!delegate_) |
181 return; | 188 return; |
182 | 189 |
183 const std::string& presentation_url_str = presentation_url.get(); | 190 if (screen_availability_listener_.get()) { |
184 auto it = availability_contexts_.find(presentation_url_str); | 191 delegate_->RemoveScreenAvailabilityListener( |
185 if (it == availability_contexts_.end()) | 192 render_process_id_, |
186 return; | 193 render_frame_id_, |
187 | 194 screen_availability_listener_.get()); |
188 delegate_->RemoveScreenAvailabilityListener( | 195 screen_availability_listener_.reset(); |
189 render_process_id_, render_frame_id_, it->second.get()); | 196 } |
190 // Resolve the context's pending callbacks before removing it. | |
191 it->second->OnScreenAvailabilityChanged(false); | |
192 availability_contexts_.erase(it); | |
193 } | 197 } |
194 | 198 |
195 void PresentationServiceImpl::ListenForDefaultSessionStart( | 199 void PresentationServiceImpl::ListenForDefaultSessionStart( |
196 const DefaultSessionMojoCallback& callback) { | 200 const DefaultSessionMojoCallback& callback) { |
197 if (!default_session_start_context_.get()) | 201 if (!default_session_start_context_.get()) |
198 default_session_start_context_.reset(new DefaultSessionStartContext); | 202 default_session_start_context_.reset(new DefaultSessionStartContext); |
199 default_session_start_context_->AddCallback(callback); | 203 default_session_start_context_->AddCallback(callback); |
200 } | 204 } |
201 | 205 |
202 void PresentationServiceImpl::StartSession( | 206 void PresentationServiceImpl::StartSession( |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 presentation::PresentationErrorPtr error) { | 319 presentation::PresentationErrorPtr error) { |
316 auto it = pending_session_cbs_.find(request_session_id); | 320 auto it = pending_session_cbs_.find(request_session_id); |
317 if (it == pending_session_cbs_.end()) | 321 if (it == pending_session_cbs_.end()) |
318 return; | 322 return; |
319 | 323 |
320 DCHECK(it->second.get()); | 324 DCHECK(it->second.get()); |
321 it->second->Run(session.Pass(), error.Pass()); | 325 it->second->Run(session.Pass(), error.Pass()); |
322 pending_session_cbs_.erase(it); | 326 pending_session_cbs_.erase(it); |
323 } | 327 } |
324 | 328 |
325 void PresentationServiceImpl::DoSetDefaultPresentationUrl( | |
326 const std::string& default_presentation_url, | |
327 const std::string& default_presentation_id) { | |
328 DCHECK(delegate_); | |
329 delegate_->SetDefaultPresentationUrl( | |
330 render_process_id_, | |
331 render_frame_id_, | |
332 default_presentation_url, | |
333 default_presentation_id); | |
334 default_presentation_url_ = default_presentation_url; | |
335 default_presentation_id_ = default_presentation_id; | |
336 } | |
337 | |
338 void PresentationServiceImpl::SetDefaultPresentationURL( | 329 void PresentationServiceImpl::SetDefaultPresentationURL( |
339 const mojo::String& default_presentation_url, | 330 const mojo::String& default_presentation_url, |
340 const mojo::String& default_presentation_id) { | 331 const mojo::String& default_presentation_id) { |
341 DVLOG(2) << "SetDefaultPresentationURL"; | 332 DVLOG(2) << "SetDefaultPresentationURL"; |
342 if (!delegate_) | 333 if (!delegate_) |
343 return; | 334 return; |
344 | 335 |
345 const std::string& old_default_url = default_presentation_url_; | 336 const std::string& old_default_url = default_presentation_url_; |
346 const std::string& new_default_url = default_presentation_url.get(); | 337 const std::string& new_default_url = default_presentation_url.get(); |
347 | 338 |
348 // Don't call delegate if nothing changed. | 339 // Don't call delegate if nothing changed. |
349 if (old_default_url == new_default_url && | 340 if (old_default_url == new_default_url && |
350 default_presentation_id_ == default_presentation_id) { | 341 default_presentation_id_ == default_presentation_id) { |
351 return; | 342 return; |
352 } | 343 } |
353 | 344 |
354 auto old_it = availability_contexts_.find(old_default_url); | 345 if (old_default_url != new_default_url) { |
355 // Haven't started listening yet. | 346 // If DPU changed, replace screen availability listeners if any. |
356 if (old_it == availability_contexts_.end()) { | 347 if (screen_availability_listener_.get()) |
357 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); | 348 ResetScreenAvailabilityListener(new_default_url); |
358 return; | |
359 } | 349 } |
360 | 350 |
361 // Have already started listening. Create a listener for the new URL and | 351 delegate_->SetDefaultPresentationUrl( |
362 // transfer the callbacks from the old listener, if any. | |
363 // This is done so that a listener added before default URL is changed | |
364 // will continue to work. | |
365 ScreenAvailabilityContext* context = | |
366 GetOrCreateAvailabilityContext(new_default_url); | |
367 old_it->second->PassPendingCallbacks(context); | |
368 | |
369 // Remove listener for old default presentation URL. | |
370 delegate_->RemoveScreenAvailabilityListener( | |
371 render_process_id_, | 352 render_process_id_, |
372 render_frame_id_, | 353 render_frame_id_, |
373 old_it->second.get()); | 354 default_presentation_url, |
374 availability_contexts_.erase(old_it); | 355 default_presentation_id); |
375 DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); | 356 default_presentation_url_ = default_presentation_url; |
| 357 default_presentation_id_ = default_presentation_id; |
376 } | 358 } |
377 | 359 |
378 | 360 |
379 void PresentationServiceImpl::SendSessionMessage( | 361 void PresentationServiceImpl::SendSessionMessage( |
380 presentation::SessionMessagePtr session_message, | 362 presentation::SessionMessagePtr session_message, |
381 const SendMessageMojoCallback& callback) { | 363 const SendMessageMojoCallback& callback) { |
382 DVLOG(2) << "SendSessionMessage"; | 364 DVLOG(2) << "SendSessionMessage"; |
383 DCHECK(!session_message.is_null()); | 365 DCHECK(!session_message.is_null()); |
384 // send_message_callback_ should be null by now, otherwise resetting of | 366 // send_message_callback_ should be null by now, otherwise resetting of |
385 // send_message_callback_ with new callback will drop the old callback. | 367 // send_message_callback_ with new callback will drop the old callback. |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 delete this; | 482 delete this; |
501 } | 483 } |
502 | 484 |
503 void PresentationServiceImpl::Reset() { | 485 void PresentationServiceImpl::Reset() { |
504 DVLOG(2) << "PresentationServiceImpl::Reset"; | 486 DVLOG(2) << "PresentationServiceImpl::Reset"; |
505 if (delegate_) | 487 if (delegate_) |
506 delegate_->Reset(render_process_id_, render_frame_id_); | 488 delegate_->Reset(render_process_id_, render_frame_id_); |
507 | 489 |
508 default_presentation_url_.clear(); | 490 default_presentation_url_.clear(); |
509 default_presentation_id_.clear(); | 491 default_presentation_id_.clear(); |
510 availability_contexts_.clear(); | 492 screen_availability_listener_.reset(); |
511 queued_start_session_requests_.clear(); | 493 queued_start_session_requests_.clear(); |
512 FlushNewSessionCallbacks(); | 494 FlushNewSessionCallbacks(); |
513 default_session_start_context_.reset(); | 495 default_session_start_context_.reset(); |
514 if (on_session_messages_callback_.get()) { | 496 if (on_session_messages_callback_.get()) { |
515 on_session_messages_callback_->Run( | 497 on_session_messages_callback_->Run( |
516 mojo::Array<presentation::SessionMessagePtr>()); | 498 mojo::Array<presentation::SessionMessagePtr>()); |
517 on_session_messages_callback_.reset(); | 499 on_session_messages_callback_.reset(); |
518 } | 500 } |
519 if (send_message_callback_) { | 501 if (send_message_callback_) { |
520 // Run the callback with false, indicating the renderer to stop sending | 502 // Run the callback with false, indicating the renderer to stop sending |
(...skipping 17 matching lines...) Expand all Loading... |
538 delegate_ = nullptr; | 520 delegate_ = nullptr; |
539 Reset(); | 521 Reset(); |
540 } | 522 } |
541 | 523 |
542 void PresentationServiceImpl::OnDefaultPresentationStarted( | 524 void PresentationServiceImpl::OnDefaultPresentationStarted( |
543 const PresentationSessionInfo& session) { | 525 const PresentationSessionInfo& session) { |
544 if (default_session_start_context_.get()) | 526 if (default_session_start_context_.get()) |
545 default_session_start_context_->set_session(session); | 527 default_session_start_context_->set_session(session); |
546 } | 528 } |
547 | 529 |
548 PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext( | 530 PresentationServiceImpl::ScreenAvailabilityListenerImpl |
549 const std::string& presentation_url) | 531 ::ScreenAvailabilityListenerImpl( |
550 : presentation_url_(presentation_url) { | 532 const std::string& presentation_url, |
| 533 PresentationServiceImpl* service) |
| 534 : presentation_url_(presentation_url), |
| 535 service_(service) { |
| 536 DCHECK(service_); |
| 537 DCHECK(service_->client_.get()); |
551 } | 538 } |
552 | 539 |
553 PresentationServiceImpl::ScreenAvailabilityContext:: | 540 PresentationServiceImpl::ScreenAvailabilityListenerImpl:: |
554 ~ScreenAvailabilityContext() { | 541 ~ScreenAvailabilityListenerImpl() { |
555 // Ensure that pending callbacks are flushed. | |
556 OnScreenAvailabilityChanged(false); | |
557 } | 542 } |
558 | 543 |
559 void PresentationServiceImpl::ScreenAvailabilityContext::CallbackReceived( | 544 std::string PresentationServiceImpl::ScreenAvailabilityListenerImpl |
560 const ScreenAvailabilityMojoCallback& callback) { | |
561 // NOTE: This will overwrite previously registered callback if any. | |
562 if (!available_ptr_) { | |
563 // No results yet, store callback for later invocation. | |
564 callbacks_.push_back(new ScreenAvailabilityMojoCallback(callback)); | |
565 } else { | |
566 // Run callback now, reset result. | |
567 // There shouldn't be any callbacks stored in this scenario. | |
568 DCHECK(!HasPendingCallbacks()); | |
569 callback.Run(presentation_url_, *available_ptr_); | |
570 available_ptr_.reset(); | |
571 } | |
572 } | |
573 | |
574 std::string PresentationServiceImpl::ScreenAvailabilityContext | |
575 ::GetPresentationUrl() const { | 545 ::GetPresentationUrl() const { |
576 return presentation_url_; | 546 return presentation_url_; |
577 } | 547 } |
578 | 548 |
579 void PresentationServiceImpl::ScreenAvailabilityContext | 549 void PresentationServiceImpl::ScreenAvailabilityListenerImpl |
580 ::OnScreenAvailabilityChanged(bool available) { | 550 ::OnScreenAvailabilityChanged(bool available) { |
581 if (!HasPendingCallbacks()) { | 551 service_->client_->OnScreenAvailabilityUpdated(available); |
582 // No callback, stash the result for now. | |
583 available_ptr_.reset(new bool(available)); | |
584 } else { | |
585 // Invoke callbacks and erase them. | |
586 // There shouldn't be any result stored in this scenario. | |
587 DCHECK(!available_ptr_); | |
588 ScopedVector<ScreenAvailabilityMojoCallback> callbacks; | |
589 callbacks.swap(callbacks_); | |
590 for (const auto& callback : callbacks) | |
591 callback->Run(presentation_url_, available); | |
592 } | |
593 } | |
594 | |
595 void PresentationServiceImpl::ScreenAvailabilityContext | |
596 ::PassPendingCallbacks( | |
597 PresentationServiceImpl::ScreenAvailabilityContext* other) { | |
598 std::vector<ScreenAvailabilityMojoCallback*> callbacks; | |
599 callbacks_.release(&callbacks); | |
600 std::copy(callbacks.begin(), callbacks.end(), | |
601 std::back_inserter(other->callbacks_)); | |
602 } | |
603 | |
604 bool PresentationServiceImpl::ScreenAvailabilityContext | |
605 ::HasPendingCallbacks() const { | |
606 return !callbacks_.empty(); | |
607 } | 552 } |
608 | 553 |
609 PresentationServiceImpl::StartSessionRequest::StartSessionRequest( | 554 PresentationServiceImpl::StartSessionRequest::StartSessionRequest( |
610 const std::string& presentation_url, | 555 const std::string& presentation_url, |
611 const std::string& presentation_id, | 556 const std::string& presentation_id, |
612 const NewSessionMojoCallback& callback) | 557 const NewSessionMojoCallback& callback) |
613 : presentation_url_(presentation_url), | 558 : presentation_url_(presentation_url), |
614 presentation_id_(presentation_id), | 559 presentation_id_(presentation_id), |
615 callback_(callback) { | 560 callback_(callback) { |
616 } | 561 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
664 void PresentationServiceImpl::DefaultSessionStartContext::Reset() { | 609 void PresentationServiceImpl::DefaultSessionStartContext::Reset() { |
665 ScopedVector<DefaultSessionMojoCallback> callbacks; | 610 ScopedVector<DefaultSessionMojoCallback> callbacks; |
666 callbacks.swap(callbacks_); | 611 callbacks.swap(callbacks_); |
667 for (const auto& callback : callbacks) | 612 for (const auto& callback : callbacks) |
668 callback->Run(presentation::PresentationSessionInfoPtr()); | 613 callback->Run(presentation::PresentationSessionInfoPtr()); |
669 session_.reset(); | 614 session_.reset(); |
670 } | 615 } |
671 | 616 |
672 } // namespace content | 617 } // namespace content |
673 | 618 |
OLD | NEW |