|  | // 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 "modules/presentation/PresentationReceiver.h" | 
|  |  | 
|  | #include "bindings/core/v8/ScriptPromise.h" | 
|  | #include "bindings/core/v8/ScriptPromiseResolver.h" | 
|  | #include "core/dom/DOMException.h" | 
|  | #include "core/dom/Document.h" | 
|  | #include "core/dom/ExceptionCode.h" | 
|  | #include "core/dom/ExecutionContext.h" | 
|  | #include "core/frame/Deprecation.h" | 
|  | #include "core/frame/LocalDOMWindow.h" | 
|  | #include "core/frame/LocalFrame.h" | 
|  | #include "core/frame/LocalFrameClient.h" | 
|  | #include "core/frame/Navigator.h" | 
|  | #include "core/frame/UseCounter.h" | 
|  | #include "modules/presentation/NavigatorPresentation.h" | 
|  | #include "modules/presentation/Presentation.h" | 
|  | #include "modules/presentation/PresentationConnection.h" | 
|  | #include "modules/presentation/PresentationConnectionList.h" | 
|  | #include "public/platform/modules/presentation/WebPresentationClient.h" | 
|  | #include "services/service_manager/public/cpp/interface_provider.h" | 
|  |  | 
|  | namespace blink { | 
|  |  | 
|  | PresentationReceiver::PresentationReceiver(LocalFrame* frame, | 
|  | WebPresentationClient* client) | 
|  | : ContextLifecycleObserver(frame->GetDocument()), | 
|  | receiver_binding_(this), | 
|  | client_(client) { | 
|  | connection_list_ = new PresentationConnectionList(frame->GetDocument()); | 
|  |  | 
|  | if (client) | 
|  | client->SetReceiver(this); | 
|  | } | 
|  |  | 
|  | // static | 
|  | PresentationReceiver* PresentationReceiver::From(Document& document) { | 
|  | if (!document.IsInMainFrame() || !document.GetFrame()->DomWindow()) | 
|  | return nullptr; | 
|  | Navigator& navigator = *document.GetFrame()->DomWindow()->navigator(); | 
|  | Presentation* presentation = NavigatorPresentation::presentation(navigator); | 
|  | if (!presentation) | 
|  | return nullptr; | 
|  |  | 
|  | return presentation->receiver(); | 
|  | } | 
|  |  | 
|  | ScriptPromise PresentationReceiver::connectionList(ScriptState* script_state) { | 
|  | ExecutionContext* execution_context = ExecutionContext::From(script_state); | 
|  | RecordOriginTypeAccess(*execution_context); | 
|  | if (!connection_list_property_) { | 
|  | connection_list_property_ = new ConnectionListProperty( | 
|  | execution_context, this, ConnectionListProperty::kReady); | 
|  | } | 
|  |  | 
|  | if (!connection_list_->IsEmpty() && connection_list_property_->GetState() == | 
|  | ScriptPromisePropertyBase::kPending) | 
|  | connection_list_property_->Resolve(connection_list_); | 
|  |  | 
|  | return connection_list_property_->Promise(script_state->World()); | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::Init() { | 
|  | DCHECK(!receiver_binding_.is_bound()); | 
|  |  | 
|  | mojom::blink::PresentationServicePtr presentation_service; | 
|  | auto* interface_provider = GetFrame()->Client()->GetInterfaceProvider(); | 
|  | interface_provider->GetInterface(mojo::MakeRequest(&presentation_service)); | 
|  |  | 
|  | mojom::blink::PresentationReceiverPtr receiver_ptr; | 
|  | receiver_binding_.Bind(mojo::MakeRequest(&receiver_ptr)); | 
|  | presentation_service->SetReceiver(std::move(receiver_ptr)); | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::OnReceiverTerminated() { | 
|  | for (auto& connection : connection_list_->connections()) | 
|  | connection->OnReceiverTerminated(); | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::Terminate() { | 
|  | if (!GetFrame()) | 
|  | return; | 
|  |  | 
|  | auto* window = GetFrame()->DomWindow(); | 
|  | if (!window || window->closed()) | 
|  | return; | 
|  |  | 
|  | window->close(window); | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::RemoveConnection( | 
|  | ReceiverPresentationConnection* connection) { | 
|  | DCHECK(connection_list_); | 
|  | connection_list_->RemoveConnection(connection); | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::OnReceiverConnectionAvailable( | 
|  | mojom::blink::PresentationInfoPtr info, | 
|  | mojom::blink::PresentationConnectionPtr controller_connection, | 
|  | mojom::blink::PresentationConnectionRequest receiver_connection_request) { | 
|  | // Take() will call PresentationReceiver::registerConnection() | 
|  | // and register the connection. | 
|  | auto* connection = ReceiverPresentationConnection::Take( | 
|  | this, *info, std::move(controller_connection), | 
|  | std::move(receiver_connection_request)); | 
|  |  | 
|  | // Only notify receiver.connectionList property if it has been acccessed | 
|  | // previously. | 
|  | if (!connection_list_property_) | 
|  | return; | 
|  |  | 
|  | if (connection_list_property_->GetState() == | 
|  | ScriptPromisePropertyBase::kPending) { | 
|  | connection_list_property_->Resolve(connection_list_); | 
|  | } else if (connection_list_property_->GetState() == | 
|  | ScriptPromisePropertyBase::kResolved) { | 
|  | connection_list_->DispatchConnectionAvailableEvent(connection); | 
|  | } | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::RegisterConnection( | 
|  | ReceiverPresentationConnection* connection) { | 
|  | DCHECK(connection_list_); | 
|  | connection_list_->AddConnection(connection); | 
|  | } | 
|  |  | 
|  | // static | 
|  | void PresentationReceiver::RecordOriginTypeAccess( | 
|  | ExecutionContext& execution_context) { | 
|  | if (execution_context.IsSecureContext()) { | 
|  | UseCounter::Count(&execution_context, | 
|  | WebFeature::kPresentationReceiverSecureOrigin); | 
|  | } else { | 
|  | Deprecation::CountDeprecation( | 
|  | &execution_context, WebFeature::kPresentationReceiverInsecureOrigin); | 
|  | } | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::ContextDestroyed(ExecutionContext*) { | 
|  | receiver_binding_.Close(); | 
|  | if (client_) { | 
|  | client_->SetReceiver(nullptr); | 
|  | client_ = nullptr; | 
|  | } | 
|  | } | 
|  |  | 
|  | void PresentationReceiver::Trace(blink::Visitor* visitor) { | 
|  | visitor->Trace(connection_list_); | 
|  | visitor->Trace(connection_list_property_); | 
|  | ScriptWrappable::Trace(visitor); | 
|  | ContextLifecycleObserver::Trace(visitor); | 
|  | } | 
|  |  | 
|  | }  // namespace blink |