Bug 1210340 - Implement PresentationConnection.close(), r=smaug
authorKershaw Chang <kechang@mozilla.com>
Wed, 13 Jul 2016 00:18:00 +0200
changeset 304779 733ebbaf1df6fec3396d6a7e198161f8ff49f1da
parent 304778 b19a16a27943cb1c527033b332d4b3674f13dc85
child 304780 593b94c9212079e251919c556ed164b2ef7e335f
push id79422
push usercbook@mozilla.com
push dateWed, 13 Jul 2016 08:03:19 +0000
treeherdermozilla-inbound@df769eb7552e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1210340
milestone50.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 1210340 - Implement PresentationConnection.close(), r=smaug
dom/presentation/PresentationConnection.cpp
dom/presentation/PresentationConnection.h
dom/webidl/PresentationConnection.webidl
--- a/dom/presentation/PresentationConnection.cpp
+++ b/dom/presentation/PresentationConnection.cpp
@@ -85,48 +85,38 @@ PresentationConnection::Init()
     return false;
   }
 
   nsresult rv = service->RegisterSessionListener(mId, mRole, this);
   if(NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
 
-  nsCOMPtr<nsILoadGroup> loadGroup;
-  GetLoadGroup(getter_AddRefs(loadGroup));
-  if(NS_WARN_IF(!loadGroup)) {
-    return false;
-  }
-
-  rv = loadGroup->AddRequest(this, nullptr);
+  rv = AddIntoLoadGroup();
   if(NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
-  mWeakLoadGroup = do_GetWeakReference(loadGroup);
 
   return true;
 }
 
 void
 PresentationConnection::Shutdown()
 {
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if (NS_WARN_IF(!service)) {
     return;
   }
 
   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;
-  }
+  rv = RemoveFromLoadGroup();
+  NS_WARN_IF(NS_FAILED(rv));
 }
 
 /* virtual */ void
 PresentationConnection::DisconnectFromOwner()
 {
   NS_WARN_IF(NS_FAILED(ProcessConnectionWentAway()));
   DOMEventTargetHelper::DisconnectFromOwner();
 }
@@ -171,30 +161,41 @@ PresentationConnection::Send(const nsASt
   if(NS_WARN_IF(NS_FAILED(rv))) {
     aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
   }
 }
 
 void
 PresentationConnection::Close(ErrorResult& aRv)
 {
-  // It only works when the state is CONNECTED.
-  if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
+  // It only works when the state is CONNECTED or CONNECTING.
+  if (NS_WARN_IF(mState != PresentationConnectionState::Connected &&
+                 mState != PresentationConnectionState::Connecting)) {
     return;
   }
 
-  // TODO Bug 1210340 - Support close semantics.
-  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
+  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->CloseSession(mId,
+                          mRole,
+                          nsIPresentationService::CLOSED_REASON_CLOSED)));
 }
 
 void
 PresentationConnection::Terminate(ErrorResult& aRv)
 {
-  // It only works when the state is CONNECTED.
-  if (NS_WARN_IF(mState != PresentationConnectionState::Connected)) {
+  // It only works when the state is CONNECTED or CONNECTING.
+  if (NS_WARN_IF(mState != PresentationConnectionState::Connected &&
+                 mState != PresentationConnectionState::Connecting)) {
     return;
   }
 
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if(NS_WARN_IF(!service)) {
     aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
     return;
@@ -271,33 +272,37 @@ PresentationConnection::ProcessStateChan
                                                          name,
                                                          message))) {
           mozilla::GetErrorName(aReason, message);
           message.InsertLiteral("Internal error: ", 0);
         }
         CopyUTF8toUTF16(message, errorMsg);
       }
 
-      return DispatchConnectionClosedEvent(reason, errorMsg);
+      NS_WARN_IF(NS_FAILED(DispatchConnectionClosedEvent(reason, errorMsg)));
+
+      return RemoveFromLoadGroup();
     }
     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();
+      NS_WARN_IF(NS_FAILED(asyncDispatcher->PostDOMEvent()));
+
+      return RemoveFromLoadGroup();
     }
     default:
       MOZ_CRASH("Unknown presentation session state.");
       return NS_ERROR_INVALID_ARG;
   }
 }
 
 NS_IMETHODIMP
@@ -470,8 +475,47 @@ PresentationConnection::GetLoadFlags(nsL
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationConnection::SetLoadFlags(nsLoadFlags aLoadFlags)
 {
   return NS_OK;
 }
+
+nsresult
+PresentationConnection::AddIntoLoadGroup()
+{
+  // Avoid adding to loadgroup multiple times
+  if (mWeakLoadGroup) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsILoadGroup> loadGroup;
+  nsresult rv = GetLoadGroup(getter_AddRefs(loadGroup));
+  if(NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = loadGroup->AddRequest(this, nullptr);
+  if(NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mWeakLoadGroup = do_GetWeakReference(loadGroup);
+  return NS_OK;
+}
+
+nsresult
+PresentationConnection::RemoveFromLoadGroup()
+{
+  if (!mWeakLoadGroup) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
+  if (loadGroup) {
+    mWeakLoadGroup = nullptr;
+    return loadGroup->RemoveRequest(this, nullptr, NS_OK);
+  }
+
+  return NS_OK;
+}
--- a/dom/presentation/PresentationConnection.h
+++ b/dom/presentation/PresentationConnection.h
@@ -74,16 +74,20 @@ private:
 
   nsresult DispatchConnectionClosedEvent(PresentationConnectionClosedReason aReason,
                                          const nsAString& aMessage);
 
   nsresult DispatchMessageEvent(JS::Handle<JS::Value> aData);
 
   nsresult ProcessConnectionWentAway();
 
+  nsresult AddIntoLoadGroup();
+
+  nsresult RemoveFromLoadGroup();
+
   nsString mId;
   uint8_t mRole;
   PresentationConnectionState mState;
   RefPtr<PresentationConnectionList> mOwningConnectionList;
   nsWeakPtr mWeakLoadGroup;;
 };
 
 } // namespace dom
--- a/dom/webidl/PresentationConnection.webidl
+++ b/dom/webidl/PresentationConnection.webidl
@@ -55,21 +55,20 @@ interface PresentationConnection : Event
    * It is triggered when receiving messages.
    */
   attribute EventHandler onmessage;
 
   /*
    * Both the controlling and receiving browsing context can close the
    * connection. Then the connection state should turn into "closed".
    *
-   * This function only works when the state is not "connected".
+   * This function only works when the state is "connected" or "connecting".
    */
-  // TODO Bug 1210340 - Support close semantics.
-  // [Throws]
-  // void close();
+  [Throws]
+  void close();
 
   /*
    * Both the controlling and receiving browsing context can terminate the
    * connection. Then the connection state should turn into "terminated".
    *
    * This function only works when the state is not "connected".
    */
    [Throws]