Bug 1311944 - notify device disconnect only when session termination. r=smaug
authorShih-Chiang Chien <schien@mozilla.com>
Mon, 24 Oct 2016 19:11:26 +0800
changeset 319338 a151abb7d9f8f6ebd044e2b3e02e89b0bf20ebe5
parent 319337 ef16dca832723f5023ee5af5ddcf87a02d1e9188
child 319339 26747674755376db9774f034d0bbd2bc1f4e9b4b
push id33528
push userschien@mozilla.com
push dateWed, 26 Oct 2016 01:32:55 +0000
treeherderautoland@a151abb7d9f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1311944
milestone52.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 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() {