diff options
Diffstat (limited to '')
-rw-r--r-- | dom/presentation/PresentationReceiver.cpp | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/dom/presentation/PresentationReceiver.cpp b/dom/presentation/PresentationReceiver.cpp new file mode 100644 index 0000000000..6eb9c87b8a --- /dev/null +++ b/dom/presentation/PresentationReceiver.cpp @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "PresentationReceiver.h" + +#include "mozilla/Logging.h" +#include "mozilla/dom/PresentationReceiverBinding.h" +#include "mozilla/dom/Promise.h" +#include "nsContentUtils.h" +#include "nsIDocShell.h" +#include "nsIPresentationService.h" +#include "nsPIDOMWindow.h" +#include "nsServiceManagerUtils.h" +#include "nsThreadUtils.h" +#include "PresentationConnection.h" +#include "PresentationConnectionList.h" +#include "PresentationLog.h" + +namespace mozilla { +namespace dom { + +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PresentationReceiver, mOwner, + mGetConnectionListPromise, + mConnectionList) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationReceiver) +NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationReceiver) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationReceiver) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY + NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener) + NS_INTERFACE_MAP_ENTRY(nsISupports) +NS_INTERFACE_MAP_END + +/* static */ +already_AddRefed<PresentationReceiver> PresentationReceiver::Create( + nsPIDOMWindowInner* aWindow) { + RefPtr<PresentationReceiver> receiver = new PresentationReceiver(aWindow); + return NS_WARN_IF(!receiver->Init()) ? nullptr : receiver.forget(); +} + +PresentationReceiver::PresentationReceiver(nsPIDOMWindowInner* aWindow) + : mOwner(aWindow) { + MOZ_ASSERT(aWindow); +} + +PresentationReceiver::~PresentationReceiver() { Shutdown(); } + +bool PresentationReceiver::Init() { + if (NS_WARN_IF(!mOwner)) { + return false; + } + mWindowId = mOwner->WindowID(); + + nsCOMPtr<nsIDocShell> docShell = mOwner->GetDocShell(); + MOZ_ASSERT(docShell); + + nsContentUtils::GetPresentationURL(docShell, mUrl); + return !mUrl.IsEmpty(); +} + +void PresentationReceiver::Shutdown() { + PRES_DEBUG("receiver shutdown:windowId[%" PRId64 "]\n", mWindowId); + + // Unregister listener for incoming sessions. + nsCOMPtr<nsIPresentationService> service = + do_GetService(PRESENTATION_SERVICE_CONTRACTID); + if (NS_WARN_IF(!service)) { + return; + } + + Unused << NS_WARN_IF( + NS_FAILED(service->UnregisterRespondingListener(mWindowId))); +} + +/* virtual */ +JSObject* PresentationReceiver::WrapObject(JSContext* aCx, + JS::Handle<JSObject*> aGivenProto) { + return PresentationReceiver_Binding::Wrap(aCx, this, aGivenProto); +} + +NS_IMETHODIMP +PresentationReceiver::NotifySessionConnect(uint64_t aWindowId, + const nsAString& aSessionId) { + PRES_DEBUG("receiver session connect:id[%s], windowId[%" PRIx64 "]\n", + NS_ConvertUTF16toUTF8(aSessionId).get(), aWindowId); + + if (NS_WARN_IF(!mOwner)) { + return NS_ERROR_FAILURE; + } + + if (NS_WARN_IF(aWindowId != mWindowId)) { + return NS_ERROR_INVALID_ARG; + } + + if (NS_WARN_IF(!mConnectionList)) { + return NS_ERROR_FAILURE; + } + + RefPtr<PresentationConnection> connection = PresentationConnection::Create( + mOwner, aSessionId, mUrl, nsIPresentationService::ROLE_RECEIVER, + mConnectionList); + if (NS_WARN_IF(!connection)) { + return NS_ERROR_NOT_AVAILABLE; + } + + return NS_OK; +} + +already_AddRefed<Promise> PresentationReceiver::GetConnectionList( + ErrorResult& aRv) { + nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mOwner); + if (NS_WARN_IF(!global)) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + if (!mGetConnectionListPromise) { + mGetConnectionListPromise = Promise::Create(global, aRv); + if (NS_WARN_IF(aRv.Failed())) { + return nullptr; + } + + RefPtr<PresentationReceiver> self = this; + nsresult rv = NS_DispatchToMainThread(NS_NewRunnableFunction( + "dom::PresentationReceiver::GetConnectionList", + [self]() -> void { self->CreateConnectionList(); })); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } + } + + RefPtr<Promise> promise = mGetConnectionListPromise; + if (nsContentUtils::ShouldResistFingerprinting()) { + promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); + } + return promise.forget(); +} + +void PresentationReceiver::CreateConnectionList() { + MOZ_ASSERT(mGetConnectionListPromise); + + if (mConnectionList) { + return; + } + + mConnectionList = + new PresentationConnectionList(mOwner, mGetConnectionListPromise); + + // Register listener for incoming sessions. + nsCOMPtr<nsIPresentationService> service = + do_GetService(PRESENTATION_SERVICE_CONTRACTID); + if (NS_WARN_IF(!service)) { + mGetConnectionListPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR); + return; + } + + nsresult rv = service->RegisterRespondingListener(mWindowId, this); + if (NS_WARN_IF(NS_FAILED(rv))) { + mGetConnectionListPromise->MaybeReject(rv); + } +} + +} // namespace dom +} // namespace mozilla |