Bug 1258602 - Part1: Add PresentationConnectionList, r=smaug

This commit is contained in:
Kershaw Chang 2016-05-29 19:59:00 +02:00
parent 6ba3ad8ecf
commit 70abe8c5e3
14 changed files with 353 additions and 158 deletions

View File

@ -50,8 +50,7 @@ PresentationRequesterCallback::NotifySuccess()
// channel is ready. So we simply set the connection state as connected. // channel is ready. So we simply set the connection state as connected.
RefPtr<PresentationConnection> connection = RefPtr<PresentationConnection> connection =
PresentationConnection::Create(mRequest->GetOwner(), mSessionId, PresentationConnection::Create(mRequest->GetOwner(), mSessionId,
nsIPresentationService::ROLE_CONTROLLER, nsIPresentationService::ROLE_CONTROLLER);
PresentationConnectionState::Connected);
if (NS_WARN_IF(!connection)) { if (NS_WARN_IF(!connection)) {
mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR); mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
return NS_OK; return NS_OK;

View File

@ -13,6 +13,7 @@
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsStringStream.h" #include "nsStringStream.h"
#include "PresentationConnection.h" #include "PresentationConnection.h"
#include "PresentationConnectionList.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::dom; using namespace mozilla::dom;
@ -20,10 +21,12 @@ using namespace mozilla::dom;
NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationConnection) NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationConnection)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwningConnectionList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper)
tmp->Shutdown(); tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwningConnectionList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(PresentationConnection, DOMEventTargetHelper) NS_IMPL_ADDREF_INHERITED(PresentationConnection, DOMEventTargetHelper)
@ -36,10 +39,11 @@ NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow, PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow,
const nsAString& aId, const nsAString& aId,
const uint8_t aRole, const uint8_t aRole,
PresentationConnectionState aState) PresentationConnectionList* aList)
: DOMEventTargetHelper(aWindow) : DOMEventTargetHelper(aWindow)
, mId(aId) , mId(aId)
, mState(aState) , mState(PresentationConnectionState::Connecting)
, mOwningConnectionList(aList)
{ {
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER); aRole == nsIPresentationService::ROLE_RECEIVER);
@ -54,12 +58,12 @@ PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow,
PresentationConnection::Create(nsPIDOMWindowInner* aWindow, PresentationConnection::Create(nsPIDOMWindowInner* aWindow,
const nsAString& aId, const nsAString& aId,
const uint8_t aRole, const uint8_t aRole,
PresentationConnectionState aState) PresentationConnectionList* aList)
{ {
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER || MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER); aRole == nsIPresentationService::ROLE_RECEIVER);
RefPtr<PresentationConnection> connection = RefPtr<PresentationConnection> connection =
new PresentationConnection(aWindow, aId, aRole, aState); new PresentationConnection(aWindow, aId, aRole, aList);
return NS_WARN_IF(!connection->Init()) ? nullptr : connection.forget(); return NS_WARN_IF(!connection->Init()) ? nullptr : connection.forget();
} }
@ -186,6 +190,9 @@ PresentationConnection::NotifyStateChange(const nsAString& aSessionId,
PresentationConnectionState state; PresentationConnectionState state;
switch (aState) { switch (aState) {
case nsIPresentationSessionListener::STATE_CONNECTING:
state = PresentationConnectionState::Connecting;
break;
case nsIPresentationSessionListener::STATE_CONNECTED: case nsIPresentationSessionListener::STATE_CONNECTED:
state = PresentationConnectionState::Connected; state = PresentationConnectionState::Connected;
break; break;
@ -220,7 +227,16 @@ PresentationConnection::NotifyStateChange(const nsAString& aSessionId,
} }
} }
return DispatchStateChangeEvent(); nsresult rv = DispatchStateChangeEvent();
if(NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
if (mOwningConnectionList) {
mOwningConnectionList->NotifyStateChange(aSessionId, this);
}
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP

View File

@ -14,6 +14,8 @@
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class PresentationConnectionList;
class PresentationConnection final : public DOMEventTargetHelper class PresentationConnection final : public DOMEventTargetHelper
, public nsIPresentationSessionListener , public nsIPresentationSessionListener
{ {
@ -23,10 +25,11 @@ public:
DOMEventTargetHelper) DOMEventTargetHelper)
NS_DECL_NSIPRESENTATIONSESSIONLISTENER NS_DECL_NSIPRESENTATIONSESSIONLISTENER
static already_AddRefed<PresentationConnection> Create(nsPIDOMWindowInner* aWindow, static already_AddRefed<PresentationConnection>
const nsAString& aId, Create(nsPIDOMWindowInner* aWindow,
const uint8_t aRole, const nsAString& aId,
PresentationConnectionState aState); const uint8_t aRole,
PresentationConnectionList* aList = nullptr);
virtual void DisconnectFromOwner() override; virtual void DisconnectFromOwner() override;
@ -52,7 +55,7 @@ private:
PresentationConnection(nsPIDOMWindowInner* aWindow, PresentationConnection(nsPIDOMWindowInner* aWindow,
const nsAString& aId, const nsAString& aId,
const uint8_t aRole, const uint8_t aRole,
PresentationConnectionState aState); PresentationConnectionList* aList);
~PresentationConnection(); ~PresentationConnection();
@ -67,6 +70,7 @@ private:
nsString mId; nsString mId;
uint8_t mRole; uint8_t mRole;
PresentationConnectionState mState; PresentationConnectionState mState;
RefPtr<PresentationConnectionList> mOwningConnectionList;
}; };
} // namespace dom } // namespace dom

View File

@ -0,0 +1,125 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "PresentationConnectionList.h"
#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/PresentationConnectionAvailableEvent.h"
#include "mozilla/dom/PresentationConnectionListBinding.h"
#include "mozilla/dom/Promise.h"
#include "PresentationConnection.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(PresentationConnectionList, DOMEventTargetHelper,
mGetConnectionListPromise,
mConnections)
NS_IMPL_ADDREF_INHERITED(PresentationConnectionList, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(PresentationConnectionList, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationConnectionList)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
PresentationConnectionList::PresentationConnectionList(nsPIDOMWindowInner* aWindow,
Promise* aPromise)
: DOMEventTargetHelper(aWindow)
, mGetConnectionListPromise(aPromise)
{
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aPromise);
}
/* virtual */ JSObject*
PresentationConnectionList::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto)
{
return PresentationConnectionListBinding::Wrap(aCx, this, aGivenProto);
}
void
PresentationConnectionList::GetConnections(
nsTArray<RefPtr<PresentationConnection>>& aConnections) const
{
aConnections = mConnections;
}
nsresult
PresentationConnectionList::DispatchConnectionAvailableEvent(
PresentationConnection* aConnection)
{
PresentationConnectionAvailableEventInit init;
init.mConnection = aConnection;
RefPtr<PresentationConnectionAvailableEvent> event =
PresentationConnectionAvailableEvent::Constructor(
this,
NS_LITERAL_STRING("connectionavailable"),
init);
if (NS_WARN_IF(!event)) {
return NS_ERROR_FAILURE;
}
event->SetTrusted(true);
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, event);
return asyncDispatcher->PostDOMEvent();
}
PresentationConnectionList::ConnectionArrayIndex
PresentationConnectionList::FindConnectionById(
const nsAString& aId)
{
for (ConnectionArrayIndex i = 0; i < mConnections.Length(); i++) {
nsAutoString id;
mConnections[i]->GetId(id);
if (id == nsAutoString(aId)) {
return i;
}
}
return mConnections.NoIndex;
}
void
PresentationConnectionList::NotifyStateChange(const nsAString& aSessionId,
PresentationConnection* aConnection)
{
if (!aConnection) {
MOZ_ASSERT(false, "PresentationConnection can not be null.");
return;
}
bool connectionFound =
FindConnectionById(aSessionId) != mConnections.NoIndex ? true : false;
PresentationConnectionListBinding::ClearCachedConnectionsValue(this);
switch (aConnection->State()) {
case PresentationConnectionState::Connected:
if (!connectionFound) {
mConnections.AppendElement(aConnection);
if (mGetConnectionListPromise) {
mGetConnectionListPromise->MaybeResolve(this);
mGetConnectionListPromise = nullptr;
return;
}
}
DispatchConnectionAvailableEvent(aConnection);
break;
case PresentationConnectionState::Terminated:
if (connectionFound) {
mConnections.RemoveElement(aConnection);
}
break;
default:
break;
}
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef mozilla_dom_PresentationConnectionList_h
#define mozilla_dom_PresentationConnectionList_h
#include "mozilla/DOMEventTargetHelper.h"
#include "nsTArray.h"
namespace mozilla {
namespace dom {
class PresentationConnection;
class Promise;
class PresentationConnectionList final : public DOMEventTargetHelper
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationConnectionList,
DOMEventTargetHelper)
PresentationConnectionList(nsPIDOMWindowInner* aWindow,
Promise* aPromise);
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
void GetConnections(nsTArray<RefPtr<PresentationConnection>>& aConnections) const;
void NotifyStateChange(const nsAString& aSessionId, PresentationConnection* aConnection);
IMPL_EVENT_HANDLER(connectionavailable);
private:
virtual ~PresentationConnectionList() = default;
nsresult DispatchConnectionAvailableEvent(PresentationConnection* aConnection);
typedef nsTArray<RefPtr<PresentationConnection>> ConnectionArray;
typedef ConnectionArray::index_type ConnectionArrayIndex;
ConnectionArrayIndex FindConnectionById(const nsAString& aId);
RefPtr<Promise> mGetConnectionListPromise;
// This array stores only non-terminsted connections.
ConnectionArray mConnections;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_PresentationConnectionList_h

View File

@ -4,37 +4,31 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/AsyncEventDispatcher.h" #include "PresentationReceiver.h"
#include "mozilla/dom/PresentationReceiverBinding.h" #include "mozilla/dom/PresentationReceiverBinding.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationService.h" #include "nsIPresentationService.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "PresentationReceiver.h" #include "nsThreadUtils.h"
#include "PresentationConnection.h" #include "PresentationConnection.h"
#include "PresentationConnectionList.h"
using namespace mozilla; namespace mozilla {
using namespace mozilla::dom; namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationReceiver) NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(PresentationReceiver,
mOwner,
mGetConnectionListPromise,
mConnectionList)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PresentationReceiver, DOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTING_ADDREF(PresentationReceiver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnections) NS_IMPL_CYCLE_COLLECTING_RELEASE(PresentationReceiver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingGetConnectionPromises)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PresentationReceiver, DOMEventTargetHelper) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PresentationReceiver)
tmp->Shutdown(); NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConnections)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingGetConnectionPromises)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_ADDREF_INHERITED(PresentationReceiver, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(PresentationReceiver, DOMEventTargetHelper)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationReceiver)
NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener) NS_INTERFACE_MAP_ENTRY(nsIPresentationRespondingListener)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) NS_INTERFACE_MAP_END
/* static */ already_AddRefed<PresentationReceiver> /* static */ already_AddRefed<PresentationReceiver>
PresentationReceiver::Create(nsPIDOMWindowInner* aWindow) PresentationReceiver::Create(nsPIDOMWindowInner* aWindow)
@ -44,8 +38,9 @@ PresentationReceiver::Create(nsPIDOMWindowInner* aWindow)
} }
PresentationReceiver::PresentationReceiver(nsPIDOMWindowInner* aWindow) PresentationReceiver::PresentationReceiver(nsPIDOMWindowInner* aWindow)
: DOMEventTargetHelper(aWindow) : mOwner(aWindow)
{ {
MOZ_ASSERT(aWindow);
} }
PresentationReceiver::~PresentationReceiver() PresentationReceiver::~PresentationReceiver()
@ -56,31 +51,16 @@ PresentationReceiver::~PresentationReceiver()
bool bool
PresentationReceiver::Init() PresentationReceiver::Init()
{ {
if (NS_WARN_IF(!GetOwner())) { if (NS_WARN_IF(!mOwner)) {
return false;
}
mWindowId = GetOwner()->WindowID();
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return false;
}
// Register listener for incoming sessions.
nsresult rv = service->RegisterRespondingListener(mWindowId, this);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false; return false;
} }
mWindowId = mOwner->WindowID();
return true; return true;
} }
void PresentationReceiver::Shutdown() void PresentationReceiver::Shutdown()
{ {
mConnections.Clear();
mPendingGetConnectionPromises.Clear();
// Unregister listener for incoming sessions. // Unregister listener for incoming sessions.
nsCOMPtr<nsIPresentationService> service = nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID); do_GetService(PRESENTATION_SERVICE_CONTRACTID);
@ -92,13 +72,6 @@ void PresentationReceiver::Shutdown()
NS_WARN_IF(NS_FAILED(rv)); NS_WARN_IF(NS_FAILED(rv));
} }
/* virtual */ void
PresentationReceiver::DisconnectFromOwner()
{
Shutdown();
DOMEventTargetHelper::DisconnectFromOwner();
}
/* virtual */ JSObject* /* virtual */ JSObject*
PresentationReceiver::WrapObject(JSContext* aCx, PresentationReceiver::WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) JS::Handle<JSObject*> aGivenProto)
@ -106,86 +79,88 @@ PresentationReceiver::WrapObject(JSContext* aCx,
return PresentationReceiverBinding::Wrap(aCx, this, aGivenProto); return PresentationReceiverBinding::Wrap(aCx, this, aGivenProto);
} }
already_AddRefed<Promise>
PresentationReceiver::GetConnection(ErrorResult& aRv)
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
// If there's no existing connection, leave the promise pending until a
// connecting request arrives from the controlling browsing context (sender).
// http://w3c.github.io/presentation-api/#dom-presentation-getconnection
if (!mConnections.IsEmpty()) {
promise->MaybeResolve(mConnections[0]);
} else {
mPendingGetConnectionPromises.AppendElement(promise);
}
return promise.forget();
}
already_AddRefed<Promise>
PresentationReceiver::GetConnections(ErrorResult& aRv) const
{
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
RefPtr<Promise> promise = Promise::Create(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
promise->MaybeResolve(mConnections);
return promise.forget();
}
NS_IMETHODIMP NS_IMETHODIMP
PresentationReceiver::NotifySessionConnect(uint64_t aWindowId, PresentationReceiver::NotifySessionConnect(uint64_t aWindowId,
const nsAString& aSessionId) const nsAString& aSessionId)
{ {
if (NS_WARN_IF(!GetOwner())) { if (NS_WARN_IF(!mOwner)) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) { if (NS_WARN_IF(aWindowId != mWindowId)) {
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
} }
if (NS_WARN_IF(!mConnectionList)) {
return NS_ERROR_FAILURE;
}
RefPtr<PresentationConnection> connection = RefPtr<PresentationConnection> connection =
PresentationConnection::Create(GetOwner(), aSessionId, PresentationConnection::Create(mOwner, aSessionId,
nsIPresentationService::ROLE_RECEIVER, nsIPresentationService::ROLE_RECEIVER,
PresentationConnectionState::Closed); mConnectionList);
if (NS_WARN_IF(!connection)) { if (NS_WARN_IF(!connection)) {
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
mConnections.AppendElement(connection);
// Resolve pending |GetConnection| promises if any. return NS_OK;
if (!mPendingGetConnectionPromises.IsEmpty()) { }
for(uint32_t i = 0; i < mPendingGetConnectionPromises.Length(); i++) {
mPendingGetConnectionPromises[i]->MaybeResolve(connection); already_AddRefed<Promise>
} PresentationReceiver::GetConnectionList(ErrorResult& aRv)
mPendingGetConnectionPromises.Clear(); {
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mOwner);
if (NS_WARN_IF(!global)) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
} }
return DispatchConnectionAvailableEvent(); 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([self] () -> void {
self->CreateConnectionList();
}));
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return nullptr;
}
}
RefPtr<Promise> promise = mGetConnectionListPromise;
return promise.forget();
} }
nsresult void
PresentationReceiver::DispatchConnectionAvailableEvent() PresentationReceiver::CreateConnectionList()
{ {
RefPtr<AsyncEventDispatcher> asyncDispatcher = MOZ_ASSERT(mGetConnectionListPromise);
new AsyncEventDispatcher(this, NS_LITERAL_STRING("connectionavailable"), false);
return asyncDispatcher->PostDOMEvent(); 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

View File

@ -7,55 +7,55 @@
#ifndef mozilla_dom_PresentationReceiver_h #ifndef mozilla_dom_PresentationReceiver_h
#define mozilla_dom_PresentationReceiver_h #define mozilla_dom_PresentationReceiver_h
#include "mozilla/DOMEventTargetHelper.h" #include "nsCycleCollectionParticipant.h"
#include "nsIPresentationListener.h" #include "nsIPresentationListener.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class Promise;
class PresentationConnection; class PresentationConnection;
class PresentationConnectionList;
class Promise;
class PresentationReceiver final : public DOMEventTargetHelper class PresentationReceiver final : public nsIPresentationRespondingListener
, public nsIPresentationRespondingListener , public nsWrapperCache
{ {
public: public:
NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationReceiver, NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PresentationReceiver)
DOMEventTargetHelper)
NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER NS_DECL_NSIPRESENTATIONRESPONDINGLISTENER
static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindowInner* aWindow); static already_AddRefed<PresentationReceiver> Create(nsPIDOMWindowInner* aWindow);
virtual void DisconnectFromOwner() override;
virtual JSObject* WrapObject(JSContext* aCx, virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override; JS::Handle<JSObject*> aGivenProto) override;
nsISupports* GetParentObject() const
{
return mOwner;
}
// WebIDL (public APIs) // WebIDL (public APIs)
already_AddRefed<Promise> GetConnection(ErrorResult& aRv); already_AddRefed<Promise> GetConnectionList(ErrorResult& aRv);
already_AddRefed<Promise> GetConnections(ErrorResult& aRv) const;
IMPL_EVENT_HANDLER(connectionavailable);
private: private:
explicit PresentationReceiver(nsPIDOMWindowInner* aWindow); explicit PresentationReceiver(nsPIDOMWindowInner* aWindow);
~PresentationReceiver(); virtual ~PresentationReceiver();
bool Init(); bool Init();
void Shutdown(); void Shutdown();
nsresult DispatchConnectionAvailableEvent(); void CreateConnectionList();
// Store the inner window ID for |UnregisterRespondingListener| call in // Store the inner window ID for |UnregisterRespondingListener| call in
// |Shutdown| since the inner window may not exist at that moment. // |Shutdown| since the inner window may not exist at that moment.
uint64_t mWindowId; uint64_t mWindowId;
nsTArray<RefPtr<PresentationConnection>> mConnections; nsCOMPtr<nsPIDOMWindowInner> mOwner;
nsTArray<RefPtr<Promise>> mPendingGetConnectionPromises; RefPtr<Promise> mGetConnectionListPromise;
RefPtr<PresentationConnectionList> mConnectionList;
}; };
} // namespace dom } // namespace dom

View File

@ -44,7 +44,7 @@ public:
, mSessionId(aSessionId) , mSessionId(aSessionId)
, mIsResponderReady(false) , mIsResponderReady(false)
, mIsTransportReady(false) , mIsTransportReady(false)
, mState(nsIPresentationSessionListener::STATE_CLOSED) , mState(nsIPresentationSessionListener::STATE_CONNECTING)
, mCallback(aCallback) , mCallback(aCallback)
{ {
MOZ_ASSERT(!mUrl.IsEmpty()); MOZ_ASSERT(!mUrl.IsEmpty());

View File

@ -16,9 +16,10 @@ interface nsIPresentationAvailabilityListener : nsISupports
[scriptable, uuid(7dd48df8-8f8c-48c7-ac37-7b9fd1acf2f8)] [scriptable, uuid(7dd48df8-8f8c-48c7-ac37-7b9fd1acf2f8)]
interface nsIPresentationSessionListener : nsISupports interface nsIPresentationSessionListener : nsISupports
{ {
const unsigned short STATE_CONNECTED = 0; const unsigned short STATE_CONNECTING = 0;
const unsigned short STATE_CLOSED = 1; const unsigned short STATE_CONNECTED = 1;
const unsigned short STATE_TERMINATED = 2; const unsigned short STATE_CLOSED = 2;
const unsigned short STATE_TERMINATED = 3;
/* /*
* Called when session state changes. * Called when session state changes.

View File

@ -18,6 +18,7 @@ EXPORTS.mozilla.dom += [
'PresentationAvailability.h', 'PresentationAvailability.h',
'PresentationCallbacks.h', 'PresentationCallbacks.h',
'PresentationConnection.h', 'PresentationConnection.h',
'PresentationConnectionList.h',
'PresentationDeviceManager.h', 'PresentationDeviceManager.h',
'PresentationReceiver.h', 'PresentationReceiver.h',
'PresentationRequest.h', 'PresentationRequest.h',
@ -35,6 +36,7 @@ UNIFIED_SOURCES += [
'PresentationAvailability.cpp', 'PresentationAvailability.cpp',
'PresentationCallbacks.cpp', 'PresentationCallbacks.cpp',
'PresentationConnection.cpp', 'PresentationConnection.cpp',
'PresentationConnectionList.cpp',
'PresentationDeviceManager.cpp', 'PresentationDeviceManager.cpp',
'PresentationReceiver.cpp', 'PresentationReceiver.cpp',
'PresentationRequest.cpp', 'PresentationRequest.cpp',

View File

@ -6,6 +6,9 @@
enum PresentationConnectionState enum PresentationConnectionState
{ {
// The initial state when a PresentationConnection is ceated.
"connecting",
// Existing presentation, and the communication channel is active. // Existing presentation, and the communication channel is active.
"connected", "connected",

View File

@ -0,0 +1,23 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*/
[Pref="dom.presentation.enabled",
Func="Navigator::HasPresentationSupport"]
interface PresentationConnectionList : EventTarget {
/*
* Return the non-terminated set of presentation connections in the
* set of presentation controllers.
* TODO: Use FrozenArray once available. (Bug 1236777)
* readonly attribute FrozenArray<PresentationConnection> connections;
*/
[Frozen, Cached, Pure]
readonly attribute sequence<PresentationConnection> connections;
/*
* It is called when an incoming connection is connected.
*/
attribute EventHandler onconnectionavailable;
};

View File

@ -6,22 +6,11 @@
[Pref="dom.presentation.enabled", [Pref="dom.presentation.enabled",
Func="Navigator::HasPresentationSupport"] Func="Navigator::HasPresentationSupport"]
interface PresentationReceiver : EventTarget { interface PresentationReceiver {
/* /*
* Get the first connected presentation connection in a receiving browsing * Get a list which contains all connected presentation connections
* context. * in a receiving browsing context.
*/ */
[Throws] [SameObject, Throws]
Promise<PresentationConnection> getConnection(); readonly attribute Promise<PresentationConnectionList> connectionList;
/*
* Get all connected presentation connections in a receiving browsing context.
*/
[Throws]
Promise<sequence<PresentationConnection>> getConnections();
/*
* It is called when an incoming connection is connecting.
*/
attribute EventHandler onconnectionavailable;
}; };

View File

@ -378,6 +378,7 @@ WEBIDL_FILES = [
'Presentation.webidl', 'Presentation.webidl',
'PresentationAvailability.webidl', 'PresentationAvailability.webidl',
'PresentationConnection.webidl', 'PresentationConnection.webidl',
'PresentationConnectionList.webidl',
'PresentationDeviceInfoManager.webidl', 'PresentationDeviceInfoManager.webidl',
'PresentationReceiver.webidl', 'PresentationReceiver.webidl',
'PresentationRequest.webidl', 'PresentationRequest.webidl',