Bug 1235123 - Part 3 - Update interfaces and implantations of nsIPresentationDevice and nsIPresentationUIGlue to support 1-UA use case, r=schien
authorKuoE0 <kuoe0.tw@gmail.com>
Thu, 28 Apr 2016 15:18:21 +0800
changeset 334229 50ec1d8e55046a5f474afe76b2ebc47c58c9687e
parent 334228 2389fb0248dbb8184edfef0e06add6fe76bdaba2
child 334230 8c0409b30c4b872f677509d007c63a3fbec44648
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersschien
bugs1235123
milestone49.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 1235123 - Part 3 - Update interfaces and implantations of nsIPresentationDevice and nsIPresentationUIGlue to support 1-UA use case, r=schien
b2g/components/PresentationRequestUIGlue.js
dom/presentation/PresentationService.cpp
dom/presentation/interfaces/nsIPresentationRequestUIGlue.idl
--- a/b2g/components/PresentationRequestUIGlue.js
+++ b/b2g/components/PresentationRequestUIGlue.js
@@ -1,85 +1,112 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict"
 
 function debug(aMsg) {
-  //dump("-*- PresentationRequestUIGlue: " + aMsg + "\n");
+  // dump("-*- PresentationRequestUIGlue: " + aMsg + "\n");
 }
 
 const { interfaces: Ci, utils: Cu, classes: Cc } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
                                   "resource://gre/modules/SystemAppProxy.jsm");
 
-function PresentationRequestUIGlue() {
-  // This is to store the session ID / resolver binding.
-  // An example of the object literal is shown below:
-  //
-  // {
-  //   "sessionId1" : resolver1,
-  //   ...
-  // }
-  this._resolvers = {};
-
-  // Listen to the result for the opened iframe from front-end.
-  SystemAppProxy.addEventListener("mozPresentationContentEvent", aEvent => {
-    let detail = aEvent.detail;
-
-    switch (detail.type) {
-      case "presentation-receiver-launched": {
-        let sessionId = detail.id;
-        let resolver = this._resolvers[sessionId];
-        if (!resolver) {
-          debug("No correspondent resolver for session ID: " + sessionId);
-          return;
-        }
-
-        delete this._resolvers[sessionId];
-        resolver.resolve(detail.frame);
-        break;
-      }
-      case "presentation-receiver-permission-denied": {
-        let sessionId = detail.id;
-        let resolver = this._resolvers[sessionId];
-        if (!resolver) {
-          debug("No correspondent resolver for session ID: " + sessionId);
-          return;
-        }
-
-        delete this._resolvers[sessionId];
-        resolver.reject();
-        break;
-      }
-      default:
-        return;
-      }
-  });
-}
+function PresentationRequestUIGlue() { }
 
 PresentationRequestUIGlue.prototype = {
 
-  sendRequest: function(aUrl, aSessionId) {
-    return new Promise(function(aResolve, aReject) {
-      this._resolvers[aSessionId] = {
-        resolve: aResolve,
-        reject: aReject,
+  sendRequest: function(aUrl, aSessionId, aDevice) {
+    let localDevice = aDevice.QueryInterface(Ci.nsIPresentationLocalDevice);
+    if (localDevice) {
+      return this.sendTo1UA(aUrl, aSessionId, localDevice.windowId);
+    } else {
+      return this.sendTo2UA(aUrl, aSessionId);
+    }
+  },
+
+  // For 1-UA scenario
+  sendTo1UA: function(aUrl, aSessionId, aWindowId) {
+    return new Promise((aResolve, aReject) => {
+      let handler = (evt) => {
+        if (evt.type === "unload") {
+          SystemAppProxy.removeEventListenerWithId(aWindowId,
+                                                   "unload",
+                                                   handler);
+          SystemAppProxy.removeEventListenerWithId(aWindowId,
+                                                   "mozPresentationContentEvent",
+                                                   handler);
+          aReject();
+        }
+        if (evt.type === "mozPresentationContentEvent" &&
+            evt.detail.id == aSessionId) {
+          SystemAppProxy.removeEventListenerWithId(aWindowId,
+                                                   "unload",
+                                                   handler);
+          SystemAppProxy.removeEventListenerWithId(aWindowId,
+                                                   "mozPresentationContentEvent",
+                                                   handler);
+          this.appLaunchCallback(evt.detail, aResolve, aReject);
+        }
+      };
+      // If system(-remote) app is closed.
+      SystemAppProxy.addEventListenerWithId(aWindowId,
+                                            "unload",
+                                            handler);
+      // Listen to the result for the opened iframe from front-end.
+      SystemAppProxy.addEventListenerWithId(aWindowId,
+                                            "mozPresentationContentEvent",
+                                            handler);
+      SystemAppProxy.sendCustomEventWithId(aWindowId,
+                                           "mozPresentationChromeEvent",
+                                           { type: "presentation-launch-receiver",
+                                             url: aUrl,
+                                             id: aSessionId });
+    });
+  },
+
+  // For 2-UA scenario
+  sendTo2UA: function(aUrl, aSessionId) {
+    return new Promise((aResolve, aReject) => {
+      let handler = (evt) => {
+        if (evt.type === "mozPresentationContentEvent" &&
+            evt.detail.id == aSessionId) {
+          SystemAppProxy.removeEventListener("mozPresentationContentEvent",
+                                            handler);
+          this.appLaunchCallback(evt.detail, aResolve, aReject);
+        }
       };
 
+      // Listen to the result for the opened iframe from front-end.
+      SystemAppProxy.addEventListener("mozPresentationContentEvent",
+                                      handler);
       SystemAppProxy._sendCustomEvent("mozPresentationChromeEvent",
                                       { type: "presentation-launch-receiver",
                                         url: aUrl,
                                         id: aSessionId });
-    }.bind(this));
+    });
+  },
+
+  appLaunchCallback: function(aDetail, aResolve, aReject) {
+    switch(aDetail.type) {
+      case "presentation-receiver-launched":
+        aResolve(aDetail.frame);
+        break;
+      case "presentation-receiver-permission-denied":
+        aReject();
+        break;
+    }
   },
 
   classID: Components.ID("{ccc8a839-0b64-422b-8a60-fb2af0e376d0}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationRequestUIGlue])
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationRequestUIGlue]);
--- a/dom/presentation/PresentationService.cpp
+++ b/dom/presentation/PresentationService.cpp
@@ -335,17 +335,17 @@ PresentationService::HandleSessionReques
   // Notify the receiver to launch.
   nsCOMPtr<nsIPresentationRequestUIGlue> glue =
     do_CreateInstance(PRESENTATION_REQUEST_UI_GLUE_CONTRACTID);
   if (NS_WARN_IF(!glue)) {
     ctrlChannel->Close(NS_ERROR_DOM_OPERATION_ERR);
     return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
   nsCOMPtr<nsISupports> promise;
-  rv = glue->SendRequest(url, sessionId, getter_AddRefs(promise));
+  rv = glue->SendRequest(url, sessionId, device, getter_AddRefs(promise));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     ctrlChannel->Close(rv);
     return info->ReplyError(NS_ERROR_DOM_OPERATION_ERR);
   }
   nsCOMPtr<Promise> realPromise = do_QueryInterface(promise);
   static_cast<PresentationPresentingInfo*>(info.get())->SetPromise(realPromise);
 
   return NS_OK;
--- a/dom/presentation/interfaces/nsIPresentationRequestUIGlue.idl
+++ b/dom/presentation/interfaces/nsIPresentationRequestUIGlue.idl
@@ -1,25 +1,29 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
+interface nsIPresentationDevice;
+
 %{C++
 #define PRESENTATION_REQUEST_UI_GLUE_CONTRACTID \
   "@mozilla.org/presentation/requestuiglue;1"
 %}
 
 [scriptable, uuid(faa45119-6fb5-496c-aa4c-f740177a38b5)]
 interface nsIPresentationRequestUIGlue : nsISupports
 {
   /*
-   * This method is called to open the responding app/page when a presentation
-   * request comes in at receiver side.
+   * This method is called to open the responding app/page when
+   * a presentation request comes in at receiver side.
    *
    * @param url       The url of the request.
    * @param sessionId The session ID of the request.
    *
    * @return A promise that resolves to the opening frame.
    */
-  nsISupports sendRequest(in DOMString url, in DOMString sessionId);
+  nsISupports sendRequest(in DOMString url,
+                          in DOMString sessionId,
+                          in nsIPresentationDevice device);
 };