Bug 1311944 - notify device disconnect only when session termination. r=smaug draft
authorShih-Chiang Chien <schien@mozilla.com>
Mon, 24 Oct 2016 19:11:26 +0800
changeset 428617 fee7609838a3c0f4b681f9ee9daed5857addeccf
parent 428476 215f9686117673a2c914ed207bc7da9bb8d741ad
child 534786 9dab6e63a0a9883f8c100dd93909cc4ed48a40a7
push id33367
push userschien@mozilla.com
push dateMon, 24 Oct 2016 11:27:03 +0000
reviewerssmaug
bugs1311944
milestone52.0a1
Bug 1311944 - notify device disconnect only when session termination. r=smaug MozReview-Commit-ID: JNVDv3L2r6t
dom/presentation/PresentationSessionInfo.cpp
dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
dom/presentation/tests/mochitest/test_presentation_terminate.js
dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -1225,20 +1225,16 @@ void
 PresentationPresentingInfo::Shutdown(nsresult aReason)
 {
   PresentationSessionInfo::Shutdown(aReason);
 
   if (mTimer) {
     mTimer->Cancel();
   }
 
-  if (mDevice) {
-    mDevice->Disconnect();
-  }
-  mDevice = nullptr;
   mLoadingCallback = nullptr;
   mRequesterDescription = nullptr;
   mPendingCandidates.Clear();
   mPromise = nullptr;
   mHasFlushPendingEvents = false;
 }
 
 // nsIPresentationSessionTransportBuilderListener
@@ -1390,16 +1386,22 @@ PresentationPresentingInfo::InitTranspor
 nsresult
 PresentationPresentingInfo::UntrackFromService()
 {
   // Remove the OOP responding info (if it has never been used).
   if (mContentParent) {
     Unused << NS_WARN_IF(!static_cast<ContentParent*>(mContentParent.get())->SendNotifyPresentationReceiverCleanUp(mSessionId));
   }
 
+  // Receiver device might need clean up after session termination.
+  if (mDevice) {
+    mDevice->Disconnect();
+  }
+  mDevice = nullptr;
+
   // Remove the session info (and the in-process responding info if there's any).
   nsCOMPtr<nsIPresentationService> service =
     do_GetService(PRESENTATION_SERVICE_CONTRACTID);
   if (NS_WARN_IF(!service)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   static_cast<PresentationService*>(service.get())->UntrackSessionInfo(mSessionId, mRole);
 
--- a/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
+++ b/dom/presentation/tests/mochitest/PresentationSessionChromeScript1UA.js
@@ -164,17 +164,19 @@ const mockDevice = {
   type: 'type',
   establishControlChannel: function(url, presentationId) {
     if (triggerControlChannelError) {
       throw Cr.NS_ERROR_FAILURE;
     }
     sendAsyncMessage('control-channel-established');
     return mockControlChannelOfSender;
   },
-  disconnect: function() {},
+  disconnect: function() {
+    sendAsyncMessage('device-disconnected');
+  },
   isRequestedUrlSupported: function(requestedUrl) {
     return true;
   },
 };
 
 const mockDevicePrompt = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevicePrompt,
                                          Ci.nsIFactory]),
--- a/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
+++ b/dom/presentation/tests/mochitest/file_presentation_1ua_receiver.html
@@ -150,17 +150,22 @@ function testConnectionClosed() {
     };
     command('forward-command', JSON.stringify({ name: 'ready-to-close' }));
   });
 }
 
 function testReconnectConnection() {
   return new Promise(function(aResolve, aReject) {
     info('Receiver: --- testReconnectConnection ---');
-    command('forward-command', JSON.stringify({ name: 'ready-to-reconnect' }));
+    window.addEventListener('hashchange', function hashchangeHandler(evt) {
+      var message = JSON.parse(decodeURIComponent(window.location.hash.substring(1)));
+      if (message.type === 'prepare-for-reconnect') {
+        command('forward-command', JSON.stringify({ name: 'ready-to-reconnect' }));
+      }
+    });
     connection.onconnect = function() {
       connection.onconnect = null;
       ok(true, "The connection is reconnected.")
       aResolve();
     };
   });
 }
 
--- a/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
+++ b/dom/presentation/tests/mochitest/test_presentation_1ua_sender_and_receiver.js
@@ -226,16 +226,34 @@ function testCloseConnection() {
         connection.onclose = null;
         is(connection.state, 'closed', 'Sender: Connection should be closed.');
         gScript.removeMessageListener('control-channel-established',
                                       controlChannelEstablishedHandler);
         aResolve();
       };
     }),
     new Promise(function(aResolve, aReject) {
+      let timeout = setTimeout(function() {
+        gScript.removeMessageListener('device-disconnected',
+                                      deviceDisconnectedHandler);
+        ok(true, "terminate after close should not trigger device.disconnect");
+        aResolve();
+      }, 3000);
+
+      function deviceDisconnectedHandler() {
+        gScript.removeMessageListener('device-disconnected',
+                                      deviceDisconnectedHandler);
+        ok(false, "terminate after close should not trigger device.disconnect");
+        clearTimeout(timeout);
+        aResolve();
+      }
+
+      gScript.addMessageListener('device-disconnected', deviceDisconnectedHandler);
+    }),
+    new Promise(function(aResolve, aReject) {
       gScript.addMessageListener('receiver-closed', function onReceiverClosed() {
         gScript.removeMessageListener('receiver-closed', onReceiverClosed);
         gScript.removeMessageListener('control-channel-established',
                                       controlChannelEstablishedHandler);
         aResolve();
       });
     }),
   ]);
@@ -289,16 +307,18 @@ function testReconnect() {
           aResolve();
         };
       }).catch((aError) => {
         ok(false, "Sender: Error occurred when establishing a connection: " + aError);
         teardown();
         aReject();
       });
     });
+
+    postMessageToIframe('prepare-for-reconnect');
   });
 }
 
 function teardown() {
   gScript.addMessageListener('teardown-complete', function teardownCompleteHandler() {
     debug('Got message: teardown-complete');
     gScript.removeMessageListener('teardown-complete', teardownCompleteHandler);
     gScript.destroy();
--- a/dom/presentation/tests/mochitest/test_presentation_terminate.js
+++ b/dom/presentation/tests/mochitest/test_presentation_terminate.js
@@ -141,20 +141,31 @@ function testConnectionTerminate() {
       gScript.removeMessageListener('control-channel-established',
                                     controlChannelEstablishedHandler);
       gScript.sendAsyncMessage('trigger-control-channel-open');
     });
     gScript.addMessageListener('sender-terminate', function senderTerminateHandler() {
       gScript.removeMessageListener('sender-terminate',
                                     senderTerminateHandler);
 
-      receiverIframe.addEventListener('mozbrowserclose', function() {
-        ok(true, 'observe receiver page closing');
-        aResolve();
-      });
+      Promise.all([
+        new Promise((resolve) => {
+          gScript.addMessageListener('device-disconnected', function deviceDisconnectedHandler() {
+            gScript.removeMessageListener('device-disconnected', deviceDisconnectedHandler);
+            ok(true, 'observe device disconnect');
+            resolve();
+          });
+        }),
+        new Promise((resolve) => {
+          receiverIframe.addEventListener('mozbrowserclose', function() {
+            ok(true, 'observe receiver page closing');
+            resolve();
+          });
+        }),
+      ]).then(aResolve);
 
       gScript.sendAsyncMessage('trigger-on-terminate-request');
     });
     gScript.addMessageListener('ready-to-terminate', function onReadyToTerminate() {
       gScript.removeMessageListener('ready-to-terminate', onReadyToTerminate);
       connection.terminate();
 
       // test unexpected close right after terminate
--- a/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
+++ b/dom/presentation/tests/mochitest/test_presentation_terminate_establish_connection_error.js
@@ -133,16 +133,25 @@ function testConnectionTerminate() {
     new Promise(function(aResolve, aReject) {
       connection.onclose = function() {
         connection.onclose = null;
         is(connection.state, 'closed', 'Sender: Connection should be closed.');
         aResolve();
       };
     }),
     new Promise(function(aResolve, aReject) {
+      function deviceDisconnectedHandler() {
+        gScript.removeMessageListener('device-disconnected', deviceDisconnectedHandler);
+        ok(true, 'should not receive device disconnect');
+        aResolve();
+      }
+
+      gScript.addMessageListener('device-disconnected', deviceDisconnectedHandler);
+    }),
+    new Promise(function(aResolve, aReject) {
       receiverIframe.addEventListener('mozbrowserclose', function() {
         ok(true, 'observe receiver page closing');
         aResolve();
       });
     })
   ]);
 
   gScript.addMessageListener('prepare-for-terminate', function prepareForTerminateHandler() {