Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #24 from KershawChang/presentationAPI
Browse files Browse the repository at this point in the history
Bug 1267965, 1258600, 1258602; a=jocheng
  • Loading branch information
xeonchen committed Jun 2, 2016
2 parents 0012104 + 1b26260 commit 8f0ee73
Show file tree
Hide file tree
Showing 46 changed files with 1,433 additions and 488 deletions.
1 change: 1 addition & 0 deletions dom/base/nsGkAtomList.h
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ GK_ATOM(onstorageareachanged, "onstorageareachanged")
GK_ATOM(onsubmit, "onsubmit")
GK_ATOM(onsuccess, "onsuccess")
GK_ATOM(ontypechange, "ontypechange")
GK_ATOM(onterminate, "onterminate")
GK_ATOM(ontext, "ontext")
GK_ATOM(ontoggle, "ontoggle")
GK_ATOM(ontouchstart, "ontouchstart")
Expand Down
3 changes: 1 addition & 2 deletions dom/presentation/PresentationCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ PresentationRequesterCallback::NotifySuccess()
// channel is ready. So we simply set the connection state as connected.
RefPtr<PresentationConnection> connection =
PresentationConnection::Create(mRequest->GetOwner(), mSessionId,
nsIPresentationService::ROLE_CONTROLLER,
PresentationConnectionState::Connected);
nsIPresentationService::ROLE_CONTROLLER);
if (NS_WARN_IF(!connection)) {
mPromise->MaybeReject(NS_ERROR_DOM_OPERATION_ERR);
return NS_OK;
Expand Down
232 changes: 210 additions & 22 deletions dom/presentation/PresentationConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,51 @@
* 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 "PresentationConnection.h"

#include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/dom/DOMException.h"
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/PresentationConnectionClosedEvent.h"
#include "mozilla/ErrorNames.h"
#include "nsContentUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsIPresentationService.h"
#include "nsServiceManagerUtils.h"
#include "nsStringStream.h"
#include "PresentationConnection.h"
#include "PresentationConnectionList.h"

using namespace mozilla;
using namespace mozilla::dom;

NS_IMPL_CYCLE_COLLECTION_CLASS(PresentationConnection)

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_UNLINK_BEGIN_INHERITED(PresentationConnection, DOMEventTargetHelper)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwningConnectionList)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

NS_IMPL_ADDREF_INHERITED(PresentationConnection, DOMEventTargetHelper)
NS_IMPL_RELEASE_INHERITED(PresentationConnection, DOMEventTargetHelper)

NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PresentationConnection)
NS_INTERFACE_MAP_ENTRY(nsIPresentationSessionListener)
NS_INTERFACE_MAP_ENTRY(nsIRequest)
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)

PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow,
const nsAString& aId,
const uint8_t aRole,
PresentationConnectionState aState)
PresentationConnectionList* aList)
: DOMEventTargetHelper(aWindow)
, mId(aId)
, mState(aState)
, mState(PresentationConnectionState::Connecting)
, mOwningConnectionList(aList)
{
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER);
Expand All @@ -54,12 +63,12 @@ PresentationConnection::PresentationConnection(nsPIDOMWindowInner* aWindow,
PresentationConnection::Create(nsPIDOMWindowInner* aWindow,
const nsAString& aId,
const uint8_t aRole,
PresentationConnectionState aState)
PresentationConnectionList* aList)
{
MOZ_ASSERT(aRole == nsIPresentationService::ROLE_CONTROLLER ||
aRole == nsIPresentationService::ROLE_RECEIVER);
RefPtr<PresentationConnection> connection =
new PresentationConnection(aWindow, aId, aRole, aState);
new PresentationConnection(aWindow, aId, aRole, aList);
return NS_WARN_IF(!connection->Init()) ? nullptr : connection.forget();
}

Expand All @@ -81,6 +90,18 @@ PresentationConnection::Init()
return false;
}

nsCOMPtr<nsILoadGroup> loadGroup;
GetLoadGroup(getter_AddRefs(loadGroup));
if(NS_WARN_IF(!loadGroup)) {
return false;
}

rv = loadGroup->AddRequest(this, nullptr);
if(NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
mWeakLoadGroup = do_GetWeakReference(loadGroup);

return true;
}

Expand All @@ -95,12 +116,18 @@ PresentationConnection::Shutdown()

nsresult rv = service->UnregisterSessionListener(mId, mRole);
NS_WARN_IF(NS_FAILED(rv));

nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
if (loadGroup) {
loadGroup->RemoveRequest(this, nullptr, NS_OK);
mWeakLoadGroup = nullptr;
}
}

/* virtual */ void
PresentationConnection::DisconnectFromOwner()
{
Shutdown();
NS_WARN_IF(NS_FAILED(ProcessConnectionWentAway()));
DOMEventTargetHelper::DisconnectFromOwner();
}

Expand Down Expand Up @@ -178,14 +205,18 @@ PresentationConnection::Terminate(ErrorResult& aRv)

NS_IMETHODIMP
PresentationConnection::NotifyStateChange(const nsAString& aSessionId,
uint16_t aState)
uint16_t aState,
nsresult aReason)
{
if (!aSessionId.Equals(mId)) {
return NS_ERROR_INVALID_ARG;
}

PresentationConnectionState state;
switch (aState) {
case nsIPresentationSessionListener::STATE_CONNECTING:
state = PresentationConnectionState::Connecting;
break;
case nsIPresentationSessionListener::STATE_CONNECTED:
state = PresentationConnectionState::Connected;
break;
Expand All @@ -203,24 +234,70 @@ PresentationConnection::NotifyStateChange(const nsAString& aSessionId,
if (mState == state) {
return NS_OK;
}

mState = state;

// Unregister session listener if the session is no longer connected.
if (mState == PresentationConnectionState::Terminated) {
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return NS_ERROR_NOT_AVAILABLE;
}

nsresult rv = service->UnregisterSessionListener(mId, mRole);
if(NS_WARN_IF(NS_FAILED(rv))) {
nsresult rv = ProcessStateChanged(aReason);
if(NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}

return DispatchStateChangeEvent();
if (mOwningConnectionList) {
mOwningConnectionList->NotifyStateChange(aSessionId, this);
}

return NS_OK;
}

nsresult
PresentationConnection::ProcessStateChanged(nsresult aReason)
{
switch (mState) {
case PresentationConnectionState::Connected: {
RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("connect"), false);
return asyncDispatcher->PostDOMEvent();
}
case PresentationConnectionState::Closed: {
PresentationConnectionClosedReason reason =
PresentationConnectionClosedReason::Closed;

nsString errorMsg;
if (NS_FAILED(aReason)) {
reason = PresentationConnectionClosedReason::Error;
nsCString name, message;

// If aReason is not a DOM error, use error name as message.
if (NS_FAILED(NS_GetNameAndMessageForDOMNSResult(aReason,
name,
message))) {
mozilla::GetErrorName(aReason, message);
message.InsertLiteral("Internal error: ", 0);
}
CopyUTF8toUTF16(message, errorMsg);
}

return DispatchConnectionClosedEvent(reason, errorMsg);
}
case PresentationConnectionState::Terminated: {
nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return NS_ERROR_NOT_AVAILABLE;
}

nsresult rv = service->UnregisterSessionListener(mId, mRole);
if(NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}

RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("terminate"), false);
return asyncDispatcher->PostDOMEvent();
}
default:
MOZ_CRASH("Unknown presentation session state.");
return NS_ERROR_INVALID_ARG;
}
}

NS_IMETHODIMP
Expand Down Expand Up @@ -252,10 +329,27 @@ PresentationConnection::NotifyMessage(const nsAString& aSessionId,
}

nsresult
PresentationConnection::DispatchStateChangeEvent()
PresentationConnection::DispatchConnectionClosedEvent(
PresentationConnectionClosedReason aReason,
const nsAString& aMessage)
{
if (mState != PresentationConnectionState::Closed) {
MOZ_ASSERT(false, "The connection state should be closed.");
return NS_ERROR_FAILURE;
}

PresentationConnectionClosedEventInit init;
init.mReason = aReason;
init.mMessage = aMessage;

RefPtr<PresentationConnectionClosedEvent> closedEvent =
PresentationConnectionClosedEvent::Constructor(this,
NS_LITERAL_STRING("close"),
init);
closedEvent->SetTrusted(true);

RefPtr<AsyncEventDispatcher> asyncDispatcher =
new AsyncEventDispatcher(this, NS_LITERAL_STRING("statechange"), false);
new AsyncEventDispatcher(this, static_cast<Event*>(closedEvent));
return asyncDispatcher->PostDOMEvent();
}

Expand Down Expand Up @@ -287,3 +381,97 @@ PresentationConnection::DispatchMessageEvent(JS::Handle<JS::Value> aData)
new AsyncEventDispatcher(this, static_cast<Event*>(messageEvent));
return asyncDispatcher->PostDOMEvent();
}

nsresult
PresentationConnection::ProcessConnectionWentAway()
{
if (mState != PresentationConnectionState::Connected &&
mState != PresentationConnectionState::Connecting) {
// If the state is not connected or connecting, do not need to
// close the session.
return NS_OK;
}

mState = PresentationConnectionState::Terminated;

nsCOMPtr<nsIPresentationService> service =
do_GetService(PRESENTATION_SERVICE_CONTRACTID);
if (NS_WARN_IF(!service)) {
return NS_ERROR_NOT_AVAILABLE;
}

return service->CloseSession(
mId, mRole, nsIPresentationService::CLOSED_REASON_WENTAWAY);
}

NS_IMETHODIMP
PresentationConnection::GetName(nsACString &aResult)
{
aResult.AssignLiteral("about:presentation-connection");
return NS_OK;
}

NS_IMETHODIMP
PresentationConnection::IsPending(bool* aRetval)
{
*aRetval = true;
return NS_OK;
}

NS_IMETHODIMP
PresentationConnection::GetStatus(nsresult* aStatus)
{
*aStatus = NS_OK;
return NS_OK;
}

NS_IMETHODIMP
PresentationConnection::Cancel(nsresult aStatus)
{
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &PresentationConnection::ProcessConnectionWentAway);
return NS_DispatchToCurrentThread(event);
}
NS_IMETHODIMP
PresentationConnection::Suspend(void)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
PresentationConnection::Resume(void)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
PresentationConnection::GetLoadGroup(nsILoadGroup** aLoadGroup)
{
*aLoadGroup = nullptr;

nsCOMPtr<nsIDocument> doc = GetOwner() ? GetOwner()->GetExtantDoc() : nullptr;
if (!doc) {
return NS_ERROR_FAILURE;
}

*aLoadGroup = doc->GetDocumentLoadGroup().take();
return NS_OK;
}

NS_IMETHODIMP
PresentationConnection::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
return NS_ERROR_UNEXPECTED;
}

NS_IMETHODIMP
PresentationConnection::GetLoadFlags(nsLoadFlags* aLoadFlags)
{
*aLoadFlags = nsIRequest::LOAD_BACKGROUND;
return NS_OK;
}

NS_IMETHODIMP
PresentationConnection::SetLoadFlags(nsLoadFlags aLoadFlags)
{
return NS_OK;
}
Loading

0 comments on commit 8f0ee73

Please sign in to comment.