Bug 1205219 - [Presentation WebAPI] Support terminate semantics. Part 1 - WebIDL & implementation changes. r=smaug
authorSean Lin <selin@mozilla.com>
Thu, 08 Oct 2015 18:11:10 +0800
changeset 266854 7acef81a1e90c1f5fc52d3ffef9e2dcb27884e5e
parent 266853 846ed9a45d55a5b27187ebd62724fc083525164f
child 266855 3cb22083aaf02e2366d7e4aaa20c81e919564435
push id29499
push userkwierso@gmail.com
push dateThu, 08 Oct 2015 21:29:10 +0000
treeherdermozilla-central@46da59584acb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1205219
milestone44.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1205219 - [Presentation WebAPI] Support terminate semantics. Part 1 - WebIDL & implementation changes. r=smaug
dom/presentation/PresentationReceiver.cpp
dom/presentation/PresentationService.cpp
dom/presentation/PresentationSession.cpp
dom/presentation/PresentationSession.h
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/PresentationSessionInfo.h
dom/presentation/interfaces/nsIPresentationListener.idl
dom/presentation/interfaces/nsIPresentationService.idl
dom/presentation/ipc/PPresentation.ipdl
dom/presentation/ipc/PresentationIPCService.cpp
dom/presentation/ipc/PresentationParent.cpp
dom/presentation/ipc/PresentationParent.h
dom/webidl/PresentationSession.webidl
--- a/dom/presentation/PresentationReceiver.cpp
+++ b/dom/presentation/PresentationReceiver.cpp
@@ -163,17 +163,17 @@ PresentationReceiver::NotifySessionConne
                                            const nsAString& aSessionId)
 {
   if (NS_WARN_IF(aWindowId != GetOwner()->WindowID())) {
     return NS_ERROR_INVALID_ARG;
   }
 
   nsRefPtr<PresentationSession> session =
     PresentationSession::Create(GetOwner(), aSessionId,
-                                PresentationSessionState::Disconnected);
+                                PresentationSessionState::Closed);
   if (NS_WARN_IF(!session)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   mSessions.AppendElement(session);
 
   // Resolve pending |GetSession| promises if any.
   if (!mPendingGetSessionPromises.IsEmpty()) {
     for(uint32_t i = 0; i < mPendingGetSessionPromises.Length(); i++) {
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -424,27 +424,41 @@ PresentationService::SendSessionMessage(
   if (NS_WARN_IF(!info)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return info->Send(aStream);
 }
 
 NS_IMETHODIMP
-PresentationService::Terminate(const nsAString& aSessionId)
+PresentationService::CloseSession(const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!aSessionId.IsEmpty());
 
   nsRefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId);
   if (NS_WARN_IF(!info)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  return info->Close(NS_OK);
+  return info->Close(NS_OK, nsIPresentationSessionListener::STATE_CLOSED);
+}
+
+NS_IMETHODIMP
+PresentationService::TerminateSession(const nsAString& aSessionId)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!aSessionId.IsEmpty());
+
+  nsRefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId);
+  if (NS_WARN_IF(!info)) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  return info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED);
 }
 
 NS_IMETHODIMP
 PresentationService::RegisterAvailabilityListener(nsIPresentationAvailabilityListener* aListener)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (NS_WARN_IF(mAvailabilityListeners.Contains(aListener))) {
@@ -490,17 +504,17 @@ PresentationService::RegisterSessionList
 
 NS_IMETHODIMP
 PresentationService::UnregisterSessionListener(const nsAString& aSessionId)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsRefPtr<PresentationSessionInfo> info = GetSessionInfo(aSessionId);
   if (info) {
-    NS_WARN_IF(NS_FAILED(info->Close(NS_OK)));
+    NS_WARN_IF(NS_FAILED(info->Close(NS_OK, nsIPresentationSessionListener::STATE_TERMINATED)));
     UntrackSessionInfo(aSessionId);
     return info->SetListener(nullptr);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationService::RegisterRespondingListener(uint64_t aWindowId,
--- a/dom/presentation/PresentationSession.cpp
+++ b/dom/presentation/PresentationSession.cpp
@@ -137,58 +137,71 @@ PresentationSession::Send(const nsAStrin
   if(NS_WARN_IF(NS_FAILED(rv))) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
 
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if(NS_WARN_IF(!service)) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
     return;
   }
 
   rv = service->SendSessionMessage(mId, stream);
   if(NS_WARN_IF(NS_FAILED(rv))) {
-    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
+    aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
   }
 }
 
 void
-PresentationSession::Close()
+PresentationSession::Close(ErrorResult& aRv)
 {
-  // Closing does nothing if the session is already terminated.
-  if (NS_WARN_IF(mState == PresentationSessionState::Terminated)) {
+  // It only works when the state is CONNECTED.
+  if (NS_WARN_IF(mState != PresentationSessionState::Connected)) {
+    return;
+  }
+
+  // TODO Bug 1210340 - Support close semantics.
+  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
+void
+PresentationSession::Terminate(ErrorResult& aRv)
+{
+  // It only works when the state is CONNECTED.
+  if (NS_WARN_IF(mState != PresentationSessionState::Connected)) {
     return;
   }
 
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if(NS_WARN_IF(!service)) {
+    aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
     return;
   }
 
-  NS_WARN_IF(NS_FAILED(service->Terminate(mId)));
+  NS_WARN_IF(NS_FAILED(service->TerminateSession(mId)));
 }
 
 NS_IMETHODIMP
 PresentationSession::NotifyStateChange(const nsAString& aSessionId,
                                        uint16_t aState)
 {
   if (!aSessionId.Equals(mId)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   PresentationSessionState state;
   switch (aState) {
     case nsIPresentationSessionListener::STATE_CONNECTED:
       state = PresentationSessionState::Connected;
       break;
-    case nsIPresentationSessionListener::STATE_DISCONNECTED:
-      state = PresentationSessionState::Disconnected;
+    case nsIPresentationSessionListener::STATE_CLOSED:
+      state = PresentationSessionState::Closed;
       break;
     case nsIPresentationSessionListener::STATE_TERMINATED:
       state = PresentationSessionState::Terminated;
       break;
     default:
       NS_WARNING("Unknown presentation session state.");
       return NS_ERROR_INVALID_ARG;
   }
--- a/dom/presentation/PresentationSession.h
+++ b/dom/presentation/PresentationSession.h
@@ -18,34 +18,36 @@ class PresentationSession final : public
                                 , public nsIPresentationSessionListener
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PresentationSession,
                                            DOMEventTargetHelper)
   NS_DECL_NSIPRESENTATIONSESSIONLISTENER
 
-  static already_AddRefed<PresentationSession>
-    Create(nsPIDOMWindow* aWindow,
-           const nsAString& aId,
-           PresentationSessionState aState);
+  static already_AddRefed<PresentationSession> Create(nsPIDOMWindow* aWindow,
+                                                      const nsAString& aId,
+                                                      PresentationSessionState aState);
 
   virtual void DisconnectFromOwner() override;
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
   // WebIDL (public APIs)
   void GetId(nsAString& aId) const;
 
   PresentationSessionState State() const;
 
-  void Send(const nsAString& aData, ErrorResult& aRv);
+  void Send(const nsAString& aData,
+            ErrorResult& aRv);
 
-  void Close();
+  void Close(ErrorResult& aRv);
+
+  void Terminate(ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(statechange);
   IMPL_EVENT_HANDLER(message);
 
 private:
   PresentationSession(nsPIDOMWindow* aWindow,
                       const nsAString& aId,
                       PresentationSessionState aState);
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -169,20 +169,17 @@ PresentationSessionInfo::SetListener(nsI
       nsresult rv = mTransport->EnableDataNotification();
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
 
     // The transport might become ready, or might become un-ready again, before
     // the listener has registered. So notify the listener of the state change.
-    uint16_t state = IsSessionReady() ?
-                     nsIPresentationSessionListener::STATE_CONNECTED :
-                     nsIPresentationSessionListener::STATE_DISCONNECTED;
-    return mListener->NotifyStateChange(mSessionId, state);
+    return mListener->NotifyStateChange(mSessionId, mState);
   }
 
   return NS_OK;
 }
 
 nsresult
 PresentationSessionInfo::Send(nsIInputStream* aData)
 {
@@ -193,46 +190,33 @@ PresentationSessionInfo::Send(nsIInputSt
   if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   return mTransport->Send(aData);
 }
 
 nsresult
-PresentationSessionInfo::Close(nsresult aReason)
+PresentationSessionInfo::Close(nsresult aReason,
+                               uint32_t aState)
 {
-  // The session is disconnected and it's a normal close. Simply change the
-  // state to TERMINATED.
-  if (!IsSessionReady() && NS_SUCCEEDED(aReason)) {
-    if (mListener) {
-      // Notify the listener and the service will untrack the session info after
-      // the listener calls |UnregisterSessionListener|.
-      nsresult rv = mListener->NotifyStateChange(mSessionId,
-                                                 nsIPresentationSessionListener::STATE_TERMINATED);
-      NS_WARN_IF(NS_FAILED(rv));
-    } else {
-      // Directly untrack the session info from the service.
-      NS_WARN_IF(NS_FAILED(UntrackFromService()));
-    }
+  if (NS_WARN_IF(!IsSessionReady())) {
+    return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
+  SetState(aState);
+
   Shutdown(aReason);
   return NS_OK;
 }
 
 nsresult
 PresentationSessionInfo::ReplySuccess()
 {
-  if (mListener) {
-    // Notify session state change.
-    nsresult rv = mListener->NotifyStateChange(mSessionId,
-                                               nsIPresentationSessionListener::STATE_CONNECTED);
-    NS_WARN_IF(NS_FAILED(rv));
-  }
+  SetState(nsIPresentationSessionListener::STATE_CONNECTED);
 
   if (mCallback) {
     NS_WARN_IF(NS_FAILED(mCallback->NotifySuccess()));
     SetCallback(nullptr);
   }
 
   return NS_OK;
 }
@@ -303,27 +287,24 @@ PresentationSessionInfo::NotifyTransport
   if (NS_WARN_IF(!IsSessionReady())) {
     // It happens before the session is ready. Reply the callback.
     return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
 
   // Unset |mIsTransportReady| here so it won't affect |IsSessionReady()| above.
   mIsTransportReady = false;
 
+  if (mState == nsIPresentationSessionListener::STATE_CONNECTED) {
+    // The transport channel is closed unexpectedly (not caused by a |Close| call).
+    SetState(nsIPresentationSessionListener::STATE_CLOSED);
+  }
+
   Shutdown(aReason);
 
-  uint16_t state = (NS_WARN_IF(NS_FAILED(aReason))) ?
-                   nsIPresentationSessionListener::STATE_DISCONNECTED :
-                   nsIPresentationSessionListener::STATE_TERMINATED;
-  if (mListener) {
-    // It happens after the session is ready. Notify session state change.
-    // If the new state is TERMINATED. the service will untrack the session info
-    // after the listener calls |UnregisterSessionListener|.
-    return mListener->NotifyStateChange(mSessionId, state);
-  } else if (state == nsIPresentationSessionListener::STATE_TERMINATED) {
+  if (mState == nsIPresentationSessionListener::STATE_TERMINATED) {
     // Directly untrack the session info from the service.
     return UntrackFromService();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -504,22 +485,19 @@ PresentationControllingInfo::NotifyClose
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Unset control channel here so it won't try to re-close it in potential
   // subsequent |Shutdown| calls.
   SetControlChannel(nullptr);
 
   if (NS_WARN_IF(NS_FAILED(aReason))) {
-    if (mListener) {
-      // The presentation session instance at receiver side may already exist.
-      // Change the state to TERMINATED since it never succeeds.
-      return mListener->NotifyStateChange(mSessionId,
-                                          nsIPresentationSessionListener::STATE_TERMINATED);
-    }
+    // The presentation session instance may already exist.
+    // Change the state to TERMINATED since it never succeeds.
+    SetState(nsIPresentationSessionListener::STATE_TERMINATED);
 
     // Reply error for an abnormal close.
     return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
 
   return NS_OK;
 }
 
@@ -561,21 +539,18 @@ PresentationControllingInfo::OnStopListe
 
   Shutdown(aStatus);
 
   if (NS_WARN_IF(!IsSessionReady())) {
     // It happens before the session is ready. Reply the callback.
     return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
 
-  // It happens after the session is ready. Notify session state change.
-  if (mListener) {
-    return mListener->NotifyStateChange(mSessionId,
-                                        nsIPresentationSessionListener::STATE_DISCONNECTED);
-  }
+  // It happens after the session is ready. Change the state to CLOSED.
+  SetState(nsIPresentationSessionListener::STATE_CLOSED);
 
   return NS_OK;
 }
 
 /*
  * Implementation of PresentationPresentingInfo
  *
  * During presentation session establishment, the receiver expects the following
@@ -770,22 +745,19 @@ PresentationPresentingInfo::NotifyClosed
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Unset control channel here so it won't try to re-close it in potential
   // subsequent |Shutdown| calls.
   SetControlChannel(nullptr);
 
   if (NS_WARN_IF(NS_FAILED(aReason))) {
-    if (mListener) {
-      // The presentation session instance at receiver side may already exist.
-      // Change the state to TERMINATED since it never succeeds.
-      return mListener->NotifyStateChange(mSessionId,
-                                          nsIPresentationSessionListener::STATE_TERMINATED);
-    }
+    // The presentation session instance may already exist.
+    // Change the state to TERMINATED since it never succeeds.
+    SetState(nsIPresentationSessionListener::STATE_TERMINATED);
 
     // Reply error for an abnormal close.
     return ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
 
   return NS_OK;
 }
 
--- a/dom/presentation/PresentationSessionInfo.h
+++ b/dom/presentation/PresentationSessionInfo.h
@@ -34,16 +34,17 @@ public:
 
   PresentationSessionInfo(const nsAString& aUrl,
                           const nsAString& aSessionId,
                           nsIPresentationServiceCallback* aCallback)
     : mUrl(aUrl)
     , mSessionId(aSessionId)
     , mIsResponderReady(false)
     , mIsTransportReady(false)
+    , mState(nsIPresentationSessionListener::STATE_CLOSED)
     , mCallback(aCallback)
   {
     MOZ_ASSERT(!mUrl.IsEmpty());
     MOZ_ASSERT(!mSessionId.IsEmpty());
   }
 
   virtual nsresult Init(nsIPresentationControlChannel* aControlChannel);
 
@@ -84,17 +85,18 @@ public:
     mControlChannel = aControlChannel;
     if (mControlChannel) {
       mControlChannel->SetListener(this);
     }
   }
 
   nsresult Send(nsIInputStream* aData);
 
-  nsresult Close(nsresult aReason);
+  nsresult Close(nsresult aReason,
+                 uint32_t aState);
 
   nsresult ReplyError(nsresult aReason);
 
   virtual bool IsAccessible(base::ProcessId aProcessId);
 
 protected:
   virtual ~PresentationSessionInfo()
   {
@@ -107,20 +109,36 @@ protected:
 
   bool IsSessionReady()
   {
     return mIsResponderReady && mIsTransportReady;
   }
 
   virtual nsresult UntrackFromService();
 
+  void SetState(uint32_t aState)
+  {
+    if (mState == aState) {
+      return;
+    }
+
+    mState = aState;
+
+    // Notify session state change.
+    if (mListener) {
+      nsresult rv = mListener->NotifyStateChange(mSessionId, mState);
+      NS_WARN_IF(NS_FAILED(rv));
+    }
+  }
+
   nsString mUrl;
   nsString mSessionId;
   bool mIsResponderReady;
   bool mIsTransportReady;
+  uint32_t mState; // CONNECTED, CLOSED, TERMINATED
   nsCOMPtr<nsIPresentationServiceCallback> mCallback;
   nsCOMPtr<nsIPresentationSessionListener> mListener;
   nsCOMPtr<nsIPresentationDevice> mDevice;
   nsCOMPtr<nsIPresentationSessionTransport> mTransport;
   nsCOMPtr<nsIPresentationControlChannel> mControlChannel;
 };
 
 // Session info with controlling browsing context (sender side) behaviors.
--- a/dom/presentation/interfaces/nsIPresentationListener.idl
+++ b/dom/presentation/interfaces/nsIPresentationListener.idl
@@ -8,21 +8,21 @@
 interface nsIPresentationAvailabilityListener : nsISupports
 {
   /*
    * Called when device availability changes.
    */
   void notifyAvailableChange(in bool available);
 };
 
-[scriptable, uuid(3b9ae71f-2905-4969-9117-101627c1c2ea)]
+[scriptable, uuid(7dd48df8-8f8c-48c7-ac37-7b9fd1acf2f8)]
 interface nsIPresentationSessionListener : nsISupports
 {
   const unsigned short STATE_CONNECTED = 0;
-  const unsigned short STATE_DISCONNECTED = 1;
+  const unsigned short STATE_CLOSED = 1;
   const unsigned short STATE_TERMINATED = 2;
 
   /*
    * Called when session state changes.
    */
   void notifyStateChange(in DOMString sessionId,
                          in unsigned short state);
 
--- a/dom/presentation/interfaces/nsIPresentationService.idl
+++ b/dom/presentation/interfaces/nsIPresentationService.idl
@@ -28,17 +28,17 @@ interface nsIPresentationServiceCallback
   /*
    * Called when the operation fails.
    *
    * @param error: error message.
    */
   void notifyError(in nsresult error);
 };
 
-[scriptable, uuid(5a254519-45c3-4229-9b16-f58c05b78fc6)]
+[scriptable, uuid(c177a13a-bf1a-48bf-8032-d415c3343c46)]
 interface nsIPresentationService : nsISupports
 {
   /*
    * Start a new presentation session and display a prompt box which asks users
    * to select a device.
    *
    * @param url: The url of presenting page.
    * @param sessionId: An ID to identify presentation session.
@@ -58,21 +58,28 @@ interface nsIPresentationService : nsISu
    *
    * @param sessionId: An ID to identify presentation session.
    * @param stream: The message is converted to an input stream.
    */
   void sendSessionMessage(in DOMString sessionId,
                           in nsIInputStream stream);
 
   /*
+   * Close the session.
+   *
+   * @param sessionId: An ID to identify presentation session.
+   */
+  void closeSession(in DOMString sessionId);
+
+  /*
    * Terminate the session.
    *
    * @param sessionId: An ID to identify presentation session.
    */
-  void terminate(in DOMString sessionId);
+  void terminateSession(in DOMString sessionId);
 
   /*
    * Register an availability listener. Must be called from the main thread.
    *
    * @param listener: The listener to register.
    */
   void registerAvailabilityListener(in nsIPresentationAvailabilityListener listener);
 
--- a/dom/presentation/ipc/PPresentation.ipdl
+++ b/dom/presentation/ipc/PPresentation.ipdl
@@ -20,26 +20,32 @@ struct StartSessionRequest
 };
 
 struct SendSessionMessageRequest
 {
   nsString sessionId;
   InputStreamParams data;
 };
 
-struct TerminateRequest
+struct CloseSessionRequest
+{
+  nsString sessionId;
+};
+
+struct TerminateSessionRequest
 {
   nsString sessionId;
 };
 
 union PresentationIPCRequest
 {
   StartSessionRequest;
   SendSessionMessageRequest;
-  TerminateRequest;
+  CloseSessionRequest;
+  TerminateSessionRequest;
 };
 
 sync protocol PPresentation
 {
   manager PContent;
   manages PPresentationRequest;
 
 child:
--- a/dom/presentation/ipc/PresentationIPCService.cpp
+++ b/dom/presentation/ipc/PresentationIPCService.cpp
@@ -66,21 +66,29 @@ PresentationIPCService::SendSessionMessa
   nsTArray<mozilla::ipc::FileDescriptor> fds;
   SerializeInputStream(aStream, stream, fds);
   MOZ_ASSERT(fds.IsEmpty());
 
   return SendRequest(nullptr, SendSessionMessageRequest(nsAutoString(aSessionId), stream));
 }
 
 NS_IMETHODIMP
-PresentationIPCService::Terminate(const nsAString& aSessionId)
+PresentationIPCService::CloseSession(const nsAString& aSessionId)
 {
   MOZ_ASSERT(!aSessionId.IsEmpty());
 
-  return SendRequest(nullptr, TerminateRequest(nsAutoString(aSessionId)));
+  return SendRequest(nullptr, CloseSessionRequest(nsAutoString(aSessionId)));
+}
+
+NS_IMETHODIMP
+PresentationIPCService::TerminateSession(const nsAString& aSessionId)
+{
+  MOZ_ASSERT(!aSessionId.IsEmpty());
+
+  return SendRequest(nullptr, TerminateSessionRequest(nsAutoString(aSessionId)));
 }
 
 nsresult
 PresentationIPCService::SendRequest(nsIPresentationServiceCallback* aCallback,
                                     const PresentationIPCRequest& aRequest)
 {
   if (sPresentationChild) {
     PresentationRequestChild* actor = new PresentationRequestChild(aCallback);
--- a/dom/presentation/ipc/PresentationParent.cpp
+++ b/dom/presentation/ipc/PresentationParent.cpp
@@ -69,18 +69,21 @@ PresentationParent::RecvPPresentationReq
   nsresult rv = NS_ERROR_FAILURE;
   switch (aRequest.type()) {
     case PresentationIPCRequest::TStartSessionRequest:
       rv = actor->DoRequest(aRequest.get_StartSessionRequest());
       break;
     case PresentationIPCRequest::TSendSessionMessageRequest:
       rv = actor->DoRequest(aRequest.get_SendSessionMessageRequest());
       break;
-    case PresentationIPCRequest::TTerminateRequest:
-      rv = actor->DoRequest(aRequest.get_TerminateRequest());
+    case PresentationIPCRequest::TCloseSessionRequest:
+      rv = actor->DoRequest(aRequest.get_CloseSessionRequest());
+      break;
+    case PresentationIPCRequest::TTerminateSessionRequest:
+      rv = actor->DoRequest(aRequest.get_TerminateSessionRequest());
       break;
     default:
       MOZ_CRASH("Unknown PresentationIPCRequest type");
   }
 
   return NS_WARN_IF(NS_FAILED(rv)) ? false : true;
 }
 
@@ -273,28 +276,47 @@ PresentationRequestParent::DoRequest(con
   nsresult rv = mService->SendSessionMessage(aRequest.sessionId(), stream);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NotifyError(rv);
   }
   return NotifySuccess();
 }
 
 nsresult
-PresentationRequestParent::DoRequest(const TerminateRequest& aRequest)
+PresentationRequestParent::DoRequest(const CloseSessionRequest& aRequest)
 {
   MOZ_ASSERT(mService);
 
   // Validate the accessibility (primarily for receiver side) so that a
   // compromised child process can't fake the ID.
   if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
                   IsSessionAccessible(aRequest.sessionId(), OtherPid()))) {
     return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
   }
 
-  nsresult rv = mService->Terminate(aRequest.sessionId());
+  nsresult rv = mService->CloseSession(aRequest.sessionId());
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return NotifyError(rv);
+  }
+  return NotifySuccess();
+}
+
+nsresult
+PresentationRequestParent::DoRequest(const TerminateSessionRequest& aRequest)
+{
+  MOZ_ASSERT(mService);
+
+  // Validate the accessibility (primarily for receiver side) so that a
+  // compromised child process can't fake the ID.
+  if (NS_WARN_IF(!static_cast<PresentationService*>(mService.get())->
+                  IsSessionAccessible(aRequest.sessionId(), OtherPid()))) {
+    return NotifyError(NS_ERROR_DOM_SECURITY_ERR);
+  }
+
+  nsresult rv = mService->TerminateSession(aRequest.sessionId());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return NotifyError(rv);
   }
   return NotifySuccess();
 }
 
 NS_IMETHODIMP
 PresentationRequestParent::NotifySuccess()
--- a/dom/presentation/ipc/PresentationParent.h
+++ b/dom/presentation/ipc/PresentationParent.h
@@ -84,17 +84,19 @@ private:
   virtual ~PresentationRequestParent();
 
   nsresult SendResponse(nsresult aResult);
 
   nsresult DoRequest(const StartSessionRequest& aRequest);
 
   nsresult DoRequest(const SendSessionMessageRequest& aRequest);
 
-  nsresult DoRequest(const TerminateRequest& aRequest);
+  nsresult DoRequest(const CloseSessionRequest& aRequest);
+
+  nsresult DoRequest(const TerminateSessionRequest& aRequest);
 
   bool mActorDestroyed;
   nsCOMPtr<nsIPresentationService> mService;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/webidl/PresentationSession.webidl
+++ b/dom/webidl/PresentationSession.webidl
@@ -5,65 +5,71 @@
  */
 
 enum PresentationSessionState
 {
   // Existing presentation, and the communication channel is active.
   "connected",
 
   // Existing presentation, but the communication channel is inactive.
-  "disconnected",
+  "closed",
 
   // The presentation is nonexistent anymore. It could be terminated manually,
-  // or either requesting page or presenting page is no longer available.
+  // or either controlling or receiving browsing context is no longer available.
   "terminated"
 };
 
 [Pref="dom.presentation.enabled",
  CheckAnyPermissions="presentation"]
 interface PresentationSession : EventTarget {
   /*
    * Unique id for all existing sessions.
    */
   [Constant]
   readonly attribute DOMString id;
 
   /*
-   * Please refer to PresentationSessionStateEvent.webidl for the declaration of
-   * PresentationSessionState.
-   *
-   * @value "connected", "disconnected", or "terminated".
+   * @value "connected", "closed", or "terminated".
    */
   readonly attribute PresentationSessionState state;
 
   /*
-   * It is called when session state changes. New state is dispatched with the
-   * event.
+   * It is called when session state changes.
    */
   attribute EventHandler onstatechange;
 
   /*
-   * After a communication channel has been established between the requesting
-   * page and the presenting page, send() is called to send message out, and the
-   * event handler "onmessage" will be invoked on the remote side.
+   * After a communication channel has been established between the controlling
+   * and receiving context, this function is called to send message out, and the
+   * event handler "onmessage" will be invoked at the remote side.
    *
-   * This function only works when state equals "connected".
+   * This function only works when the state is "connected".
    *
-   * @data: String literal-only for current implementation.
+   * TODO bug 1148307 Implement PresentationSessionTransport with DataChannel to
+   * support other binary types.
    */
   [Throws]
   void send(DOMString data);
 
   /*
    * It is triggered when receiving messages.
    */
   attribute EventHandler onmessage;
 
   /*
-   * Both the requesting page and the presenting page can close the session by
-   * calling terminate(). Then, the session is destroyed and its state is
-   * truned into "terminated". After getting into the state of "terminated",
-   * resumeSession() is incapable of re-establishing the connection.
+   * Both the controlling and receving browsing context can close the session.
+   * Then, the session state should turn into "closed".
    *
-   * This function does nothing if the state has already been "terminated".
+   * This function only works when the state is not "connected".
    */
-  void close();
+  // TODO Bug 1210340 - Support close semantics.
+  // [Throws]
+  // void close();
+
+  /*
+   * Both the controlling and receving browsing context can terminate the session.
+   * Then the session state should turn into "terminated".
+   *
+   * This function only works when the state is not "connected".
+   */
+   [Throws]
+   void terminate();
 };