Bug 1202582 - Part 1 - Presentation WebAPI] Ensure incoming messages are well delivered to receiver pages. Part 1 - PresentationSessionTransport. r=jdm
authorSean Lin <selin@mozilla.com>
Tue, 08 Sep 2015 16:19:35 +0800
changeset 294106 8985f4ca6bbf333a46727365de38bcd122f97d77
parent 294105 b74e8af3488c8ee0810a3324a929d6034899c241
child 294107 a3fe551ea06bd43a99cb0fc32cd876450d64e17d
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
bugs1202582
milestone43.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 1202582 - Part 1 - Presentation WebAPI] Ensure incoming messages are well delivered to receiver pages. Part 1 - PresentationSessionTransport. r=jdm
dom/presentation/PresentationSessionTransport.cpp
dom/presentation/PresentationSessionTransport.h
dom/presentation/interfaces/nsIPresentationSessionTransport.idl
dom/presentation/tests/xpcshell/test_presentation_session_transport.js
--- a/dom/presentation/PresentationSessionTransport.cpp
+++ b/dom/presentation/PresentationSessionTransport.cpp
@@ -62,16 +62,17 @@ NS_IMPL_ISUPPORTS(PresentationSessionTra
                   nsIInputStreamCallback,
                   nsIStreamListener,
                   nsIRequestObserver)
 
 PresentationSessionTransport::PresentationSessionTransport()
   : mReadyState(CLOSED)
   , mAsyncCopierActive(false)
   , mCloseStatus(NS_OK)
+  , mDataNotificationEnabled(false)
 {
 }
 
 PresentationSessionTransport::~PresentationSessionTransport()
 {
 }
 
 NS_IMETHODIMP
@@ -90,19 +91,18 @@ PresentationSessionTransport::InitWithSo
 
   nsresult rv = CreateStream();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   SetReadyState(OPEN);
 
-  rv = CreateInputStreamPump();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+  if (IsReadyToNotifyData()) {
+    return CreateInputStreamPump();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationSessionTransport::InitWithChannelDescription(nsIPresentationChannelDescription* aDescription,
                                                          nsIPresentationSessionTransportCallback* aCallback)
@@ -256,16 +256,36 @@ PresentationSessionTransport::CreateInpu
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+PresentationSessionTransport::EnableDataNotification()
+{
+  if (NS_WARN_IF(!mCallback)) {
+    return NS_ERROR_DOM_INVALID_STATE_ERR;
+  }
+
+  if (mDataNotificationEnabled) {
+    return NS_OK;
+  }
+
+  mDataNotificationEnabled = true;
+
+  if (IsReadyToNotifyData()) {
+    return CreateInputStreamPump();
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 PresentationSessionTransport::GetCallback(nsIPresentationSessionTransportCallback** aCallback)
 {
   nsCOMPtr<nsIPresentationSessionTransportCallback> callback = mCallback;
   callback.forget(aCallback);
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -273,17 +293,17 @@ PresentationSessionTransport::SetCallbac
 {
   mCallback = aCallback;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationSessionTransport::GetSelfAddress(nsINetAddr** aSelfAddress)
 {
-  if (NS_WARN_IF(mReadyState != OPEN)) {
+  if (NS_WARN_IF(!mTransport)) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   return mTransport->GetScriptableSelfAddr(aSelfAddress);
 }
 
 void
 PresentationSessionTransport::EnsureCopying()
@@ -354,16 +374,17 @@ PresentationSessionTransport::Close(nsre
 
   uint32_t count = 0;
   mMultiplexStream->GetCount(&count);
   if (!count) {
     mSocketOutputStream->Close();
   }
 
   mSocketInputStream->Close();
+  mDataNotificationEnabled = false;
 
   return NS_OK;
 }
 
 void
 PresentationSessionTransport::SetReadyState(ReadyState aReadyState)
 {
   mReadyState = aReadyState;
@@ -387,19 +408,18 @@ PresentationSessionTransport::OnTranspor
   MOZ_ASSERT(NS_IsMainThread());
 
   if (aStatus != NS_NET_STATUS_CONNECTED_TO) {
     return NS_OK;
   }
 
   SetReadyState(OPEN);
 
-  nsresult rv = CreateInputStreamPump();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+  if (IsReadyToNotifyData()) {
+    return CreateInputStreamPump();
   }
 
   return NS_OK;
 }
 
 // nsIInputStreamCallback
 NS_IMETHODIMP
 PresentationSessionTransport::OnInputStreamReady(nsIAsyncInputStream* aStream)
--- a/dom/presentation/PresentationSessionTransport.h
+++ b/dom/presentation/PresentationSessionTransport.h
@@ -68,19 +68,25 @@ private:
     CONNECTING,
     OPEN,
     CLOSING,
     CLOSED
   };
 
   void SetReadyState(ReadyState aReadyState);
 
+  bool IsReadyToNotifyData()
+  {
+    return mDataNotificationEnabled && mReadyState == OPEN;
+  }
+
   ReadyState mReadyState;
   bool mAsyncCopierActive;
   nsresult mCloseStatus;
+  bool mDataNotificationEnabled;
 
   // Raw socket streams
   nsCOMPtr<nsISocketTransport> mTransport;
   nsCOMPtr<nsIInputStream> mSocketInputStream;
   nsCOMPtr<nsIOutputStream> mSocketOutputStream;
 
   // Input stream machinery
   nsCOMPtr<nsIInputStreamPump> mInputStreamPump;
--- a/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
+++ b/dom/presentation/interfaces/nsIPresentationSessionTransport.idl
@@ -23,17 +23,17 @@ interface nsIPresentationSessionTranspor
   void notifyTransportReady();
   void notifyTransportClosed(in nsresult reason);
   void notifyData(in ACString data);
 };
 
 /*
  * App-to-App transport channel for the presentation session.
  */
-[scriptable, uuid(5a9fb9e9-b846-4c49-ad57-20ed88457295)]
+[scriptable, uuid(5d23ea5f-a7e5-4cf0-8fa5-6b0abd106bf2)]
 interface nsIPresentationSessionTransport : nsISupports
 {
   attribute nsIPresentationSessionTransportCallback callback;
   readonly attribute nsINetAddr selfAddress;
 
   /*
    * Initialize the transport channel with an existent socket transport. (This
    * is primarily used at the sender side.)
@@ -48,16 +48,22 @@ interface nsIPresentationSessionTranspor
    * primarily used at the receiver side.)
    * @param description The channel description.
    * @param callback The callback for followup notifications.
    */
   void initWithChannelDescription(in nsIPresentationChannelDescription description,
                                   in nsIPresentationSessionTransportCallback callback);
 
   /*
+   * Enable the notification for incoming data. |notifyData| of
+   * |nsIPresentationSessionTransportCallback| can start getting invoked.
+   */
+  void enableDataNotification();
+
+  /*
    * Send message to the remote endpoint.
    * @param data The message to send.
    */
   void send(in nsIInputStream data);
 
   /*
    * Close this session transport.
    * @param reason The reason for closing this session transport.
--- a/dom/presentation/tests/xpcshell/test_presentation_session_transport.js
+++ b/dom/presentation/tests/xpcshell/test_presentation_session_transport.js
@@ -90,16 +90,17 @@ function TestServer() {
 }
 
 TestServer.prototype = {
   onSocketAccepted: function(aSocket, aTransport) {
     print("Test server gets a client connection.");
     serverTransport = Cc["@mozilla.org/presentation/presentationsessiontransport;1"]
                         .createInstance(Ci.nsIPresentationSessionTransport);
     serverTransport.initWithSocketTransport(aTransport, serverCallback);
+    serverTransport.enableDataNotification();
   },
   onStopListening: function(aSocket) {
     print("Test server stops listening.");
   },
   close: function() {
     if (this.serverSocket) {
       this.serverSocket.close();
       this.serverSocket = null;
@@ -139,16 +140,19 @@ function clientSendMessage() {
 
 // Test the server sends a message an then a corresponding notification gets
 // triggered at the client side.
 function serverSendMessage() {
   var stream = Cc["@mozilla.org/io/string-input-stream;1"]
                  .createInstance(Ci.nsIStringInputStream);
   stream.setData(serverMessage, serverMessage.length);
   serverTransport.send(stream);
+  // The client enables data notification even after the incoming message has
+  // been sent, and should still be able to consume it.
+  clientTransport.enableDataNotification();
 }
 
 function transportClose() {
   clientTransport.close(Cr.NS_OK);
 }
 
 function shutdown() {
   testServer.close();