Bug 1202582 - Part 2 - [Presentation WebAPI] Ensure incoming messages are well delivered to receiver pages. Part 2 - PresentationSessionInfo. r=smaug
authorSean Lin <selin@mozilla.com>
Tue, 08 Sep 2015 16:22:22 +0800
changeset 261578 a3fe551ea06bd43a99cb0fc32cd876450d64e17d
parent 261577 8985f4ca6bbf333a46727365de38bcd122f97d77
child 261579 e21caed7a7f4bd1c5eed351997e07959d7b86320
push id64771
push userkwierso@gmail.com
push dateWed, 09 Sep 2015 20:49:01 +0000
treeherdermozilla-inbound@dd2a1d737a64 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
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 2 - [Presentation WebAPI] Ensure incoming messages are well delivered to receiver pages. Part 2 - PresentationSessionInfo. r=smaug
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
dom/presentation/tests/mochitest/file_presentation_receiver.html
dom/presentation/tests/mochitest/file_presentation_receiver_oop.html
dom/presentation/tests/mochitest/test_presentation_receiver.html
dom/presentation/tests/mochitest/test_presentation_receiver_oop.html
dom/presentation/tests/mochitest/test_presentation_sender.html
dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -157,16 +157,24 @@ PresentationSessionInfo::Shutdown(nsresu
 }
 
 nsresult
 PresentationSessionInfo::SetListener(nsIPresentationSessionListener* aListener)
 {
   mListener = aListener;
 
   if (mListener) {
+    // Enable data notification for the transport channel if it's available.
+    if (mTransport) {
+      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);
   }
 
@@ -529,16 +537,21 @@ PresentationRequesterInfo::OnSocketAccep
     return ReplyError(NS_ERROR_NOT_AVAILABLE);
   }
 
   nsresult rv = mTransport->InitWithSocketTransport(aTransport, this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  // Enable data notification if the listener has been registered.
+  if (mListener) {
+    return mTransport->EnableDataNotification();
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PresentationRequesterInfo::OnStopListening(nsIServerSocket* aServerSocket,
                                            nsresult aStatus)
 {
   MOZ_ASSERT(NS_IsMainThread());
@@ -632,16 +645,24 @@ PresentationResponderInfo::InitTransport
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsresult rv = mTransport->InitWithChannelDescription(mRequesterDescription, this);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  // Enable data notification if the listener has been registered.
+  if (mListener) {
+    rv = mTransport->EnableDataNotification();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
   // Prepare and send the answer.
   // TODO bug 1148307 Implement PresentationSessionTransport with DataChannel.
   // In the current implementation of |PresentationSessionTransport|,
   // |GetSelfAddress| cannot return the real info when it's initialized via
   // |InitWithChannelDescription|. Yet this deficiency only affects the channel
   // description for the answer, which is not actually checked at requester side.
   nsCOMPtr<nsINetAddr> selfAddr;
   rv = mTransport->GetSelfAddress(getter_AddRefs(selfAddr));
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript.js
@@ -198,16 +198,19 @@ const mockedSessionTransport = {
     var addresses = description.QueryInterface(Ci.nsIPresentationChannelDescription).tcpAddress;
     this._selfAddress = {
       QueryInterface: XPCOMUtils.generateQI([Ci.nsINetAddr]),
       address: (addresses.length > 0) ?
                 addresses.queryElementAt(0, Ci.nsISupportsCString).data : "",
       port: description.QueryInterface(Ci.nsIPresentationChannelDescription).tcpPort,
     };
   },
+  enableDataNotification: function() {
+    sendAsyncMessage('data-transport-notification-enabled');
+  },
   send: function(data) {
     var binaryStream = Cc["@mozilla.org/binaryinputstream;1"].
                        createInstance(Ci.nsIBinaryInputStream);
     binaryStream.setInputStream(data);
     var message = binaryStream.readBytes(binaryStream.available());
     sendAsyncMessage('message-sent', message);
   },
   close: function(reason) {
--- a/dom/presentation/tests/mochitest/file_presentation_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_receiver.html
@@ -50,28 +50,44 @@ function testSessionReady() {
       is(session.state, "connected", "Session state should become connected.");
       aResolve();
     };
 
     command({ name: 'trigger-incoming-offer' });
   });
 }
 
+function testIncomingMessage() {
+  return new Promise(function(aResolve, aReject) {
+    const incomingMessage = "test incoming message";
+
+    session.addEventListener('message', function messageHandler(aEvent) {
+      session.removeEventListener('message', messageHandler);
+      is(aEvent.data, incomingMessage, "An incoming message should be received.");
+      aResolve();
+    });
+
+    command({ name: 'trigger-incoming-message',
+    	      data: incomingMessage });
+  });
+}
+
 function testCloseSession() {
   return new Promise(function(aResolve, aReject) {
     session.onstatechange = function() {
       session.onstatechange = null;
       is(session.state, "terminated", "Session should be terminated.");
       aResolve();
     };
 
     session.close();
   });
 }
 
 testSessionAvailable().
 then(testSessionReady).
+then(testIncomingMessage).
 then(testCloseSession).
 then(finish);
 
 </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/file_presentation_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/file_presentation_receiver_oop.html
@@ -50,28 +50,44 @@ function testSessionReady() {
       is(session.state, "connected", "Session state should become connected.");
       aResolve();
     };
 
     command({ name: 'trigger-incoming-offer' });
   });
 }
 
+function testIncomingMessage() {
+  return new Promise(function(aResolve, aReject) {
+    const incomingMessage = "test incoming message";
+
+    session.addEventListener('message', function messageHandler(aEvent) {
+      session.removeEventListener('message', messageHandler);
+      is(aEvent.data, incomingMessage, "An incoming message should be received.");
+      aResolve();
+    });
+
+    command({ name: 'trigger-incoming-message',
+    	      data: incomingMessage });
+  });
+}
+
 function testCloseSession() {
   return new Promise(function(aResolve, aReject) {
     session.onstatechange = function() {
       session.onstatechange = null;
       is(session.state, "terminated", "Session should be terminated.");
       aResolve();
     };
 
     session.close();
   });
 }
 
 testSessionAvailable().
 then(testSessionReady).
+then(testIncomingMessage).
 then(testCloseSession).
 then(finish);
 
 </script>
 </body>
 </html>
--- a/dom/presentation/tests/mochitest/test_presentation_receiver.html
+++ b/dom/presentation/tests/mochitest/test_presentation_receiver.html
@@ -62,16 +62,21 @@ function setup() {
       info("An offer is received.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
     });
 
+    gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
+      gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
+      info("Data notification is enabled for data transport channel.");
+    });
+
     gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
       gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The data transport should be closed normally.");
     });
 
     aResolve();
   });
 }
--- a/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html
+++ b/dom/presentation/tests/mochitest/test_presentation_receiver_oop.html
@@ -111,16 +111,21 @@ function setup() {
       info("An offer is received.");
     });
 
     gScript.addMessageListener('control-channel-closed', function controlChannelClosedHandler(aReason) {
       gScript.removeMessageListener('control-channel-closed', controlChannelClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The control channel is closed normally.");
     });
 
+    gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
+      gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
+      info("Data notification is enabled for data transport channel.");
+    });
+
     gScript.addMessageListener('data-transport-closed', function dataTransportClosedHandler(aReason) {
       gScript.removeMessageListener('data-transport-closed', dataTransportClosedHandler);
       is(aReason, SpecialPowers.Cr.NS_OK, "The data transport should be closed normally.");
     });
 
     aResolve();
   });
 }
--- a/dom/presentation/tests/mochitest/test_presentation_sender.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender.html
@@ -60,16 +60,21 @@ function testStartSession() {
     });
 
     gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
       gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
       info("Data transport channel is initialized.");
       gScript.sendAsyncMessage('trigger-incoming-answer');
     });
 
+    gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
+      gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
+      info("Data notification is enabled for data transport channel.");
+    });
+
     presentation.startSession("http://example.com").then(
       function(aSession) {
         session = aSession;
         ok(session, "Session should be availlable.");
         ok(session.id, "Session ID should be set.");
         is(session.state, "connected", "Session state at sender side should be connected by default.");
         aResolve();
       },
--- a/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html
+++ b/dom/presentation/tests/mochitest/test_presentation_sender_disconnect.html
@@ -60,16 +60,21 @@ function testStartSession() {
       gScript.sendAsyncMessage('trigger-incoming-transport');
     });
 
     gScript.addMessageListener('data-transport-initialized', function dataTransportInitializedHandler() {
       gScript.removeMessageListener('data-transport-initialized', dataTransportInitializedHandler);
       info("Data transport channel is initialized.");
     });
 
+    gScript.addMessageListener('data-transport-notification-enabled', function dataTransportNotificationEnabledHandler() {
+      gScript.removeMessageListener('data-transport-notification-enabled', dataTransportNotificationEnabledHandler);
+      info("Data notification is enabled for data transport channel.");
+    });
+
     presentation.startSession("http://example.com").then(
       function(aSession) {
         session = aSession;
         ok(session, "Session should be availlable.");
         ok(session.id, "Session ID should be set.");
         is(session.state, "connected", "Session state at sender side should be connected by default.");
         aResolve();
       },