| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/presentation/presentation_service_impl.h" |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/stl_util.h" |
| #include "content/browser/presentation/presentation_type_converters.h" |
| #include "content/public/browser/content_browser_client.h" |
| #include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/content_client.h" |
| #include "content/public/common/frame_navigate_params.h" |
| #include "content/public/common/presentation_connection_message.h" |
| #include "content/public/common/presentation_constants.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| const int kInvalidRequestSessionId = -1; |
| |
| int GetNextRequestSessionId() { |
| static int next_request_session_id = 0; |
| return ++next_request_session_id; |
| } |
| |
| // Converts a PresentationConnectionMessage |input| to a ConnectionMessage. |
| // |input|: The message to convert. |
| // |pass_ownership|: If true, function may reuse strings or buffers from |
| // |input| without copying. |input| can be freely modified. |
| blink::mojom::ConnectionMessagePtr ToMojoConnectionMessage( |
| content::PresentationConnectionMessage* input, |
| bool pass_ownership) { |
| DCHECK(input); |
| blink::mojom::ConnectionMessagePtr output( |
| blink::mojom::ConnectionMessage::New()); |
| if (input->is_binary()) { |
| // binary data |
| DCHECK(input->data); |
| output->type = blink::mojom::PresentationMessageType::BINARY; |
| if (pass_ownership) { |
| output->data = std::move(*(input->data)); |
| } else { |
| output->data = *(input->data); |
| } |
| } else { |
| // string message |
| output->type = blink::mojom::PresentationMessageType::TEXT; |
| if (pass_ownership) { |
| output->message = std::move(input->message); |
| } else { |
| output->message = input->message; |
| } |
| } |
| return output; |
| } |
| |
| std::unique_ptr<PresentationConnectionMessage> GetPresentationConnectionMessage( |
| blink::mojom::ConnectionMessagePtr input) { |
| std::unique_ptr<content::PresentationConnectionMessage> output; |
| if (input.is_null()) |
| return output; |
| |
| switch (input->type) { |
| case blink::mojom::PresentationMessageType::TEXT: { |
| // Return nullptr PresentationConnectionMessage if invalid (unset |
| // |message|, |
| // set |data|, or size too large). |
| if (input->data || !input->message || |
| input->message->size() > |
| content::kMaxPresentationConnectionMessageSize) |
| return output; |
| |
| output.reset( |
| new PresentationConnectionMessage(PresentationMessageType::TEXT)); |
| output->message = std::move(input->message.value()); |
| return output; |
| } |
| case blink::mojom::PresentationMessageType::BINARY: { |
| // Return nullptr PresentationConnectionMessage if invalid (unset |data|, |
| // set |
| // |message|, or size too large). |
| if (!input->data || input->message || |
| input->data->size() > content::kMaxPresentationConnectionMessageSize) |
| return output; |
| |
| output.reset( |
| new PresentationConnectionMessage(PresentationMessageType::BINARY)); |
| output->data.reset( |
| new std::vector<uint8_t>(std::move(input->data.value()))); |
| return output; |
| } |
| } |
| |
| NOTREACHED() << "Invalid presentation message type " << input->type; |
| return output; |
| } |
| |
| void InvokeNewSessionCallbackWithError( |
| const PresentationServiceImpl::NewSessionCallback& callback) { |
| callback.Run(blink::mojom::PresentationSessionInfoPtr(), |
| blink::mojom::PresentationError::From(PresentationError( |
| PRESENTATION_ERROR_UNKNOWN, "Internal error"))); |
| } |
| |
| } // namespace |
| |
| PresentationServiceImpl::PresentationServiceImpl( |
| RenderFrameHost* render_frame_host, |
| WebContents* web_contents, |
| ControllerPresentationServiceDelegate* controller_delegate, |
| ReceiverPresentationServiceDelegate* receiver_delegate) |
| : WebContentsObserver(web_contents), |
| controller_delegate_(controller_delegate), |
| receiver_delegate_(receiver_delegate), |
| start_session_request_id_(kInvalidRequestSessionId), |
| weak_factory_(this) { |
| DCHECK(render_frame_host); |
| DCHECK(web_contents); |
| CHECK(render_frame_host->IsRenderFrameLive()); |
| |
| render_process_id_ = render_frame_host->GetProcess()->GetID(); |
| render_frame_id_ = render_frame_host->GetRoutingID(); |
| DVLOG(2) << "PresentationServiceImpl: " |
| << render_process_id_ << ", " << render_frame_id_; |
| |
| if (auto* delegate = GetPresentationServiceDelegate()) |
| delegate->AddObserver(render_process_id_, render_frame_id_, this); |
| } |
| |
| PresentationServiceImpl::~PresentationServiceImpl() { |
| DVLOG(2) << __FUNCTION__ << ": " << render_process_id_ << ", " |
| << render_frame_id_; |
| |
| if (auto* delegate = GetPresentationServiceDelegate()) |
| delegate->RemoveObserver(render_process_id_, render_frame_id_); |
| } |
| |
| // static |
| void PresentationServiceImpl::CreateMojoService( |
| RenderFrameHost* render_frame_host, |
| mojo::InterfaceRequest<blink::mojom::PresentationService> request) { |
| DVLOG(2) << "CreateMojoService"; |
| WebContents* web_contents = |
| WebContents::FromRenderFrameHost(render_frame_host); |
| DCHECK(web_contents); |
| |
| auto* browser = GetContentClient()->browser(); |
| auto* receiver_delegate = |
| browser->GetReceiverPresentationServiceDelegate(web_contents); |
| |
| // In current implementation, web_contents can be controller or receiver |
| // but not both. |
| auto* controller_delegate = |
| receiver_delegate |
| ? nullptr |
| : browser->GetControllerPresentationServiceDelegate(web_contents); |
| |
| // This object will be deleted when the RenderFrameHost is about to be |
| // deleted (RenderFrameDeleted). |
| PresentationServiceImpl* impl = new PresentationServiceImpl( |
| render_frame_host, web_contents, controller_delegate, receiver_delegate); |
| impl->Bind(std::move(request)); |
| } |
| |
| void PresentationServiceImpl::Bind( |
| mojo::InterfaceRequest<blink::mojom::PresentationService> request) { |
| binding_.reset(new mojo::Binding<blink::mojom::PresentationService>( |
| this, std::move(request))); |
| } |
| |
| void PresentationServiceImpl::SetClient( |
| blink::mojom::PresentationServiceClientPtr client) { |
| DCHECK(!client_.get()); |
| // TODO(imcheng): Set ErrorHandler to listen for errors. |
| client_ = std::move(client); |
| |
| if (receiver_delegate_) { |
| receiver_delegate_->RegisterReceiverConnectionAvailableCallback( |
| base::Bind(&PresentationServiceImpl::OnReceiverConnectionAvailable, |
| weak_factory_.GetWeakPtr())); |
| } |
| } |
| |
| void PresentationServiceImpl::ListenForScreenAvailability(const GURL& url) { |
| DVLOG(2) << "ListenForScreenAvailability " << url.spec(); |
| if (!controller_delegate_) { |
| client_->OnScreenAvailabilityUpdated(url, false); |
| return; |
| } |
| |
| if (screen_availability_listeners_.count(url)) |
| return; |
| |
| std::unique_ptr<ScreenAvailabilityListenerImpl> listener( |
| new ScreenAvailabilityListenerImpl(url, this)); |
| if (controller_delegate_->AddScreenAvailabilityListener( |
| render_process_id_, render_frame_id_, listener.get())) { |
| screen_availability_listeners_[url] = std::move(listener); |
| } else { |
| DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request."; |
| } |
| } |
| |
| void PresentationServiceImpl::StopListeningForScreenAvailability( |
| const GURL& url) { |
| DVLOG(2) << "StopListeningForScreenAvailability " << url.spec(); |
| if (!controller_delegate_) |
| return; |
| |
| auto listener_it = screen_availability_listeners_.find(url); |
| if (listener_it == screen_availability_listeners_.end()) |
| return; |
| |
| controller_delegate_->RemoveScreenAvailabilityListener( |
| render_process_id_, render_frame_id_, listener_it->second.get()); |
| screen_availability_listeners_.erase(listener_it); |
| } |
| |
| void PresentationServiceImpl::StartSession( |
| const std::vector<GURL>& presentation_urls, |
| const NewSessionCallback& callback) { |
| DVLOG(2) << "StartSession"; |
| if (!controller_delegate_) { |
| callback.Run( |
| blink::mojom::PresentationSessionInfoPtr(), |
| blink::mojom::PresentationError::From(PresentationError( |
| PRESENTATION_ERROR_NO_AVAILABLE_SCREENS, "No screens found."))); |
| return; |
| } |
| |
| // There is a StartSession request in progress. To avoid queueing up |
| // requests, the incoming request is rejected. |
| if (start_session_request_id_ != kInvalidRequestSessionId) { |
| InvokeNewSessionCallbackWithError(callback); |
| return; |
| } |
| |
| start_session_request_id_ = GetNextRequestSessionId(); |
| pending_start_session_cb_.reset(new NewSessionCallbackWrapper(callback)); |
| controller_delegate_->StartSession( |
| render_process_id_, render_frame_id_, presentation_urls, |
| base::Bind(&PresentationServiceImpl::OnStartSessionSucceeded, |
| weak_factory_.GetWeakPtr(), start_session_request_id_), |
| base::Bind(&PresentationServiceImpl::OnStartSessionError, |
| weak_factory_.GetWeakPtr(), start_session_request_id_)); |
| } |
| |
| void PresentationServiceImpl::JoinSession( |
| const std::vector<GURL>& presentation_urls, |
| const base::Optional<std::string>& presentation_id, |
| const NewSessionCallback& callback) { |
| DVLOG(2) << "JoinSession"; |
| if (!controller_delegate_) { |
| callback.Run(blink::mojom::PresentationSessionInfoPtr(), |
| blink::mojom::PresentationError::From(PresentationError( |
| PRESENTATION_ERROR_NO_PRESENTATION_FOUND, |
| "Error joining route: No matching route"))); |
| return; |
| } |
| |
| int request_session_id = RegisterJoinSessionCallback(callback); |
| if (request_session_id == kInvalidRequestSessionId) { |
| InvokeNewSessionCallbackWithError(callback); |
| return; |
| } |
| controller_delegate_->JoinSession( |
| render_process_id_, render_frame_id_, presentation_urls, |
| presentation_id.value_or(std::string()), |
| base::Bind(&PresentationServiceImpl::OnJoinSessionSucceeded, |
| weak_factory_.GetWeakPtr(), request_session_id), |
| base::Bind(&PresentationServiceImpl::OnJoinSessionError, |
| weak_factory_.GetWeakPtr(), request_session_id)); |
| } |
| |
| int PresentationServiceImpl::RegisterJoinSessionCallback( |
| const NewSessionCallback& callback) { |
| if (pending_join_session_cbs_.size() >= kMaxNumQueuedSessionRequests) |
| return kInvalidRequestSessionId; |
| |
| int request_id = GetNextRequestSessionId(); |
| pending_join_session_cbs_[request_id].reset( |
| new NewSessionCallbackWrapper(callback)); |
| return request_id; |
| } |
| |
| void PresentationServiceImpl::ListenForConnectionStateChange( |
| const PresentationSessionInfo& connection) { |
| // NOTE: Blink will automatically transition the connection's state to |
| // 'connected'. |
| if (controller_delegate_) { |
| controller_delegate_->ListenForConnectionStateChange( |
| render_process_id_, render_frame_id_, connection, |
| base::Bind(&PresentationServiceImpl::OnConnectionStateChanged, |
| weak_factory_.GetWeakPtr(), connection)); |
| } |
| } |
| |
| void PresentationServiceImpl::OnStartSessionSucceeded( |
| int request_session_id, |
| const PresentationSessionInfo& session_info) { |
| if (request_session_id != start_session_request_id_) |
| return; |
| |
| CHECK(pending_start_session_cb_.get()); |
| pending_start_session_cb_->Run( |
| blink::mojom::PresentationSessionInfo::From(session_info), |
| blink::mojom::PresentationErrorPtr()); |
| ListenForConnectionStateChange(session_info); |
| pending_start_session_cb_.reset(); |
| start_session_request_id_ = kInvalidRequestSessionId; |
| } |
| |
| void PresentationServiceImpl::OnStartSessionError( |
| int request_session_id, |
| const PresentationError& error) { |
| if (request_session_id != start_session_request_id_) |
| return; |
| |
| CHECK(pending_start_session_cb_.get()); |
| pending_start_session_cb_->Run(blink::mojom::PresentationSessionInfoPtr(), |
| blink::mojom::PresentationError::From(error)); |
| pending_start_session_cb_.reset(); |
| start_session_request_id_ = kInvalidRequestSessionId; |
| } |
| |
| void PresentationServiceImpl::OnJoinSessionSucceeded( |
| int request_session_id, |
| const PresentationSessionInfo& session_info) { |
| if (RunAndEraseJoinSessionMojoCallback( |
| request_session_id, |
| blink::mojom::PresentationSessionInfo::From(session_info), |
| blink::mojom::PresentationErrorPtr())) { |
| ListenForConnectionStateChange(session_info); |
| } |
| } |
| |
| void PresentationServiceImpl::OnJoinSessionError( |
| int request_session_id, |
| const PresentationError& error) { |
| RunAndEraseJoinSessionMojoCallback( |
| request_session_id, blink::mojom::PresentationSessionInfoPtr(), |
| blink::mojom::PresentationError::From(error)); |
| } |
| |
| bool PresentationServiceImpl::RunAndEraseJoinSessionMojoCallback( |
| int request_session_id, |
| blink::mojom::PresentationSessionInfoPtr session, |
| blink::mojom::PresentationErrorPtr error) { |
| auto it = pending_join_session_cbs_.find(request_session_id); |
| if (it == pending_join_session_cbs_.end()) |
| return false; |
| |
| DCHECK(it->second.get()); |
| it->second->Run(std::move(session), std::move(error)); |
| pending_join_session_cbs_.erase(it); |
| return true; |
| } |
| |
| void PresentationServiceImpl::SetDefaultPresentationUrls( |
| const std::vector<GURL>& presentation_urls) { |
| DVLOG(2) << "SetDefaultPresentationUrls"; |
| if (!controller_delegate_) |
| return; |
| |
| if (default_presentation_urls_ == presentation_urls) |
| return; |
| |
| default_presentation_urls_ = presentation_urls; |
| controller_delegate_->SetDefaultPresentationUrls( |
| render_process_id_, render_frame_id_, presentation_urls, |
| base::Bind(&PresentationServiceImpl::OnDefaultPresentationStarted, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| void PresentationServiceImpl::SendConnectionMessage( |
| blink::mojom::PresentationSessionInfoPtr session, |
| blink::mojom::ConnectionMessagePtr connection_message, |
| const SendConnectionMessageCallback& callback) { |
| DVLOG(2) << "SendConnectionMessage" |
| << " [id]: " << session->id; |
| DCHECK(!connection_message.is_null()); |
| // send_message_callback_ should be null by now, otherwise resetting of |
| // send_message_callback_ with new callback will drop the old callback. |
| if (!controller_delegate_ || send_message_callback_) { |
| callback.Run(false); |
| return; |
| } |
| |
| send_message_callback_.reset(new SendConnectionMessageCallback(callback)); |
| controller_delegate_->SendMessage( |
| render_process_id_, render_frame_id_, |
| session.To<PresentationSessionInfo>(), |
| GetPresentationConnectionMessage(std::move(connection_message)), |
| base::Bind(&PresentationServiceImpl::OnSendMessageCallback, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| void PresentationServiceImpl::OnSendMessageCallback(bool sent) { |
| // It is possible that Reset() is invoked before receiving this callback. |
| // So, always check send_message_callback_ for non-null. |
| if (send_message_callback_) { |
| send_message_callback_->Run(sent); |
| send_message_callback_.reset(); |
| } |
| } |
| |
| void PresentationServiceImpl::CloseConnection( |
| const GURL& presentation_url, |
| const std::string& presentation_id) { |
| DVLOG(2) << "CloseConnection " << presentation_id; |
| if (controller_delegate_) |
| controller_delegate_->CloseConnection(render_process_id_, render_frame_id_, |
| presentation_id); |
| } |
| |
| void PresentationServiceImpl::Terminate(const GURL& presentation_url, |
| const std::string& presentation_id) { |
| DVLOG(2) << "Terminate " << presentation_id; |
| if (controller_delegate_) |
| controller_delegate_->Terminate(render_process_id_, render_frame_id_, |
| presentation_id); |
| } |
| |
| void PresentationServiceImpl::OnConnectionStateChanged( |
| const PresentationSessionInfo& connection, |
| const PresentationConnectionStateChangeInfo& info) { |
| DVLOG(2) << "PresentationServiceImpl::OnConnectionStateChanged " |
| << "[presentation_id]: " << connection.presentation_id |
| << " [state]: " << info.state; |
| DCHECK(client_.get()); |
| if (info.state == PRESENTATION_CONNECTION_STATE_CLOSED) { |
| client_->OnConnectionClosed( |
| blink::mojom::PresentationSessionInfo::From(connection), |
| content::PresentationConnectionCloseReasonToMojo(info.close_reason), |
| info.message); |
| } else { |
| client_->OnConnectionStateChanged( |
| blink::mojom::PresentationSessionInfo::From(connection), |
| PresentationConnectionStateToMojo(info.state)); |
| } |
| } |
| |
| bool PresentationServiceImpl::FrameMatches( |
| content::RenderFrameHost* render_frame_host) const { |
| if (!render_frame_host) |
| return false; |
| |
| return render_frame_host->GetProcess()->GetID() == render_process_id_ && |
| render_frame_host->GetRoutingID() == render_frame_id_; |
| } |
| |
| PresentationServiceDelegate* |
| PresentationServiceImpl::GetPresentationServiceDelegate() { |
| return receiver_delegate_ |
| ? static_cast<PresentationServiceDelegate*>(receiver_delegate_) |
| : static_cast<PresentationServiceDelegate*>(controller_delegate_); |
| } |
| |
| void PresentationServiceImpl::ListenForConnectionMessages( |
| blink::mojom::PresentationSessionInfoPtr session) { |
| DVLOG(2) << "ListenForConnectionMessages"; |
| if (!controller_delegate_) |
| return; |
| |
| PresentationSessionInfo session_info(session.To<PresentationSessionInfo>()); |
| controller_delegate_->ListenForConnectionMessages( |
| render_process_id_, render_frame_id_, session_info, |
| base::Bind(&PresentationServiceImpl::OnConnectionMessages, |
| weak_factory_.GetWeakPtr(), session_info)); |
| } |
| |
| void PresentationServiceImpl::SetPresentationConnection( |
| blink::mojom::PresentationSessionInfoPtr session, |
| blink::mojom::PresentationConnectionPtr controller_connection_ptr, |
| blink::mojom::PresentationConnectionRequest receiver_connection_request) { |
| DVLOG(2) << "SetPresentationConnection"; |
| |
| if (!controller_delegate_) |
| return; |
| |
| PresentationSessionInfo session_info(session.To<PresentationSessionInfo>()); |
| controller_delegate_->ConnectToOffscreenPresentation( |
| render_process_id_, render_frame_id_, session_info, |
| std::move(controller_connection_ptr), |
| std::move(receiver_connection_request)); |
| } |
| |
| void PresentationServiceImpl::OnConnectionMessages( |
| const PresentationSessionInfo& session, |
| const std::vector<std::unique_ptr<PresentationConnectionMessage>>& messages, |
| bool pass_ownership) { |
| DCHECK(client_); |
| |
| DVLOG(2) << "OnConnectionMessages" |
| << " [id]: " << session.presentation_id; |
| std::vector<blink::mojom::ConnectionMessagePtr> mojo_messages( |
| messages.size()); |
| std::transform( |
| messages.begin(), messages.end(), mojo_messages.begin(), |
| [pass_ownership]( |
| const std::unique_ptr<PresentationConnectionMessage>& message) { |
| return ToMojoConnectionMessage(message.get(), pass_ownership); |
| }); |
| |
| client_->OnConnectionMessagesReceived( |
| blink::mojom::PresentationSessionInfo::From(session), |
| std::move(mojo_messages)); |
| } |
| |
| void PresentationServiceImpl::OnReceiverConnectionAvailable( |
| const content::PresentationSessionInfo& session_info, |
| PresentationConnectionPtr controller_connection_ptr, |
| PresentationConnectionRequest receiver_connection_request) { |
| DVLOG(2) << "PresentationServiceImpl::OnReceiverConnectionAvailable"; |
| |
| client_->OnReceiverConnectionAvailable( |
| blink::mojom::PresentationSessionInfo::From(session_info), |
| std::move(controller_connection_ptr), |
| std::move(receiver_connection_request)); |
| } |
| |
| void PresentationServiceImpl::DidNavigateAnyFrame( |
| content::RenderFrameHost* render_frame_host, |
| const content::LoadCommittedDetails& details, |
| const content::FrameNavigateParams& params) { |
| DVLOG(2) << "PresentationServiceImpl::DidNavigateAnyFrame"; |
| if (!FrameMatches(render_frame_host)) |
| return; |
| |
| std::string prev_url_host = details.previous_url.host(); |
| std::string curr_url_host = params.url.host(); |
| |
| // If a frame navigation is in-page (e.g. navigating to a fragment in |
| // same page) then we do not unregister listeners. |
| DVLOG(2) << "DidNavigateAnyFrame: " |
| << "prev host: " << prev_url_host << ", curr host: " << curr_url_host |
| << ", details.is_in_page: " << details.is_in_page; |
| if (details.is_in_page) |
| return; |
| |
| // Reset if the frame actually navigated. |
| Reset(); |
| } |
| |
| void PresentationServiceImpl::RenderFrameDeleted( |
| content::RenderFrameHost* render_frame_host) { |
| DVLOG(2) << "PresentationServiceImpl::RenderFrameDeleted"; |
| if (!FrameMatches(render_frame_host)) |
| return; |
| |
| // RenderFrameDeleted means the associated RFH is going to be deleted soon. |
| // This object should also be deleted. |
| Reset(); |
| delete this; |
| } |
| |
| void PresentationServiceImpl::WebContentsDestroyed() { |
| LOG(ERROR) << "PresentationServiceImpl is being deleted in " |
| << "WebContentsDestroyed()! This shouldn't happen since it " |
| << "should've been deleted during RenderFrameDeleted()."; |
| Reset(); |
| delete this; |
| } |
| |
| void PresentationServiceImpl::Reset() { |
| DVLOG(2) << "PresentationServiceImpl::Reset"; |
| |
| if (auto* delegate = GetPresentationServiceDelegate()) |
| delegate->Reset(render_process_id_, render_frame_id_); |
| |
| default_presentation_urls_.clear(); |
| |
| screen_availability_listeners_.clear(); |
| |
| start_session_request_id_ = kInvalidRequestSessionId; |
| pending_start_session_cb_.reset(); |
| |
| pending_join_session_cbs_.clear(); |
| |
| if (on_connection_messages_callback_.get()) { |
| on_connection_messages_callback_->Run( |
| std::vector<blink::mojom::ConnectionMessagePtr>()); |
| on_connection_messages_callback_.reset(); |
| } |
| |
| if (send_message_callback_) { |
| // Run the callback with false, indicating the renderer to stop sending |
| // the requests and invalidate all pending requests. |
| send_message_callback_->Run(false); |
| send_message_callback_.reset(); |
| } |
| } |
| |
| void PresentationServiceImpl::OnDelegateDestroyed() { |
| DVLOG(2) << "PresentationServiceImpl::OnDelegateDestroyed"; |
| controller_delegate_ = nullptr; |
| receiver_delegate_ = nullptr; |
| Reset(); |
| } |
| |
| void PresentationServiceImpl::OnDefaultPresentationStarted( |
| const PresentationSessionInfo& connection) { |
| DCHECK(client_.get()); |
| client_->OnDefaultSessionStarted( |
| blink::mojom::PresentationSessionInfo::From(connection)); |
| ListenForConnectionStateChange(connection); |
| } |
| |
| PresentationServiceImpl::ScreenAvailabilityListenerImpl:: |
| ScreenAvailabilityListenerImpl(const GURL& availability_url, |
| PresentationServiceImpl* service) |
| : availability_url_(availability_url), service_(service) { |
| DCHECK(service_); |
| DCHECK(service_->client_.get()); |
| } |
| |
| PresentationServiceImpl::ScreenAvailabilityListenerImpl:: |
| ~ScreenAvailabilityListenerImpl() { |
| } |
| |
| GURL PresentationServiceImpl::ScreenAvailabilityListenerImpl:: |
| GetAvailabilityUrl() const { |
| return availability_url_; |
| } |
| |
| void PresentationServiceImpl::ScreenAvailabilityListenerImpl |
| ::OnScreenAvailabilityChanged(bool available) { |
| service_->client_->OnScreenAvailabilityUpdated(availability_url_, available); |
| } |
| |
| void PresentationServiceImpl::ScreenAvailabilityListenerImpl |
| ::OnScreenAvailabilityNotSupported() { |
| service_->client_->OnScreenAvailabilityNotSupported(availability_url_); |
| } |
| |
| PresentationServiceImpl::NewSessionCallbackWrapper |
| ::NewSessionCallbackWrapper(const NewSessionCallback& callback) |
| : callback_(callback) { |
| } |
| |
| PresentationServiceImpl::NewSessionCallbackWrapper |
| ::~NewSessionCallbackWrapper() { |
| if (!callback_.is_null()) |
| InvokeNewSessionCallbackWithError(callback_); |
| } |
| |
| void PresentationServiceImpl::NewSessionCallbackWrapper::Run( |
| blink::mojom::PresentationSessionInfoPtr session, |
| blink::mojom::PresentationErrorPtr error) { |
| DCHECK(!callback_.is_null()); |
| callback_.Run(std::move(session), std::move(error)); |
| callback_.Reset(); |
| } |
| |
| } // namespace content |