Bug 1305352 - (Part 2) Implement PresentationRequestUIGlue on Fennec. r=snorp,r?schien draft
authorKuoE0 <kuoe0.tw@gmail.com>
Tue, 30 Aug 2016 18:16:31 +0800
changeset 437037 e1b6d9146802a7ea6bb83ce704f3b657caac5089
parent 437036 7e6cf715cb740bed376fd2d272f31ba523baf584
child 536527 4d86eca6f3c93af661b60d6ac611537c543d90bb
push id35296
push userbmo:kuoe0@mozilla.com
push dateThu, 10 Nov 2016 08:20:14 +0000
reviewerssnorp, schien
bugs1305352
milestone52.0a1
Bug 1305352 - (Part 2) Implement PresentationRequestUIGlue on Fennec. r=snorp,r?schien MozReview-Commit-ID: ISG6HS7HcPn
mobile/android/chrome/content/PresentationView.js
mobile/android/chrome/content/PresentationView.xul
mobile/android/components/MobileComponents.manifest
mobile/android/components/PresentationRequestUIGlue.js
mobile/android/components/moz.build
mobile/android/installer/package-manifest.in
--- a/mobile/android/chrome/content/PresentationView.js
+++ b/mobile/android/chrome/content/PresentationView.js
@@ -1,22 +1,63 @@
+/* -*- Mode: 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/. */
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
+const TOPIC_PRESENTATION_VIEW_READY = "presentation-view-ready";
+const TOPIC_PRESENTATION_RECEIVER_LAUNCH = "presentation-receiver:launch";
+const TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE = "presentation-receiver:launch:response";
+
 // globals Services
 Cu.import("resource://gre/modules/Services.jsm");
 
 function log(str) {
   // dump("-*- PresentationView.js -*-: " + str + "\n");
 }
 
 let PresentationView = {
   _id: null,
 
   startup: function startup() {
     // use hash as the ID of this top level window
     this._id = window.location.hash.substr(1);
+
+    // Listen "presentation-receiver:launch" sent from
+    // PresentationRequestUIGlue.
+    Services.obs.addObserver(this,TOPIC_PRESENTATION_RECEIVER_LAUNCH, false);
+
+    // Notify PresentationView is ready.
+    Services.obs.notifyObservers(null, TOPIC_PRESENTATION_VIEW_READY, this._id);
   },
+
+  stop: function stop() {
+    Services.obs.removeObserver(this, TOPIC_PRESENTATION_RECEIVER_LAUNCH);
+  },
+
+  observe: function observe(aSubject, aTopic, aData) {
+    log("Got observe: aTopic=" + aTopic);
+
+    let requestData = JSON.parse(aData);
+    if (this._id != requestData.windowId) {
+      return;
+    }
+
+    let browser = document.getElementById("content");
+    browser.setAttribute("mozpresentation", requestData.url);
+    try {
+      browser.loadURI(requestData.url);
+      Services.obs.notifyObservers(browser,
+                                  TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE,
+                                  JSON.stringify({ result: "success",
+                                                   requestId: requestData.requestId }));
+    } catch (e) {
+      Services.obs.notifyObservers(null,
+                                   TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE,
+                                   JSON.stringify({ result: "error",
+                                                    reason: e.message }));
+    }
+  }
 };
--- a/mobile/android/chrome/content/PresentationView.xul
+++ b/mobile/android/chrome/content/PresentationView.xul
@@ -1,14 +1,15 @@
 <?xml version="1.0"?>
 <!-- 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/. -->
 
 <window id="presentation-window"
         onload="PresentationView.startup();"
+        onunload="PresentationView.stop();"
         windowtype="navigator:browser"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <browser id="content" type="content-targetable" src="about:blank" flex="1"/>
 
   <script type="application/javascript" src="chrome://browser/content/PresentationView.js"/>
 </window>
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -41,16 +41,20 @@ contract @mozilla.org/prompter;1 {9a6114
 contract @mozilla.org/embedcomp/prompt-service;1 {9a61149b-2276-4a0a-b79c-be994ad106cf}
 component {80dae1e9-e0d2-4974-915f-f97050fa8068} PromptService.js
 contract @mozilla.org/network/authprompt-adapter-factory;1 {80dae1e9-e0d2-4974-915f-f97050fa8068}
 
 # PresentationDevicePrompt.js
 component {388bd149-c919-4a43-b646-d7ec57877689} PresentationDevicePrompt.js
 contract @mozilla.org/presentation-device/prompt;1 {388bd149-c919-4a43-b646-d7ec57877689}
 
+# PresentationRequestUIGlue.js
+component {9c550ef7-3ff6-4bd1-9ad1-5a3735b90d21} PresentationRequestUIGlue.js
+contract @mozilla.org/presentation/requestuiglue;1 {9c550ef7-3ff6-4bd1-9ad1-5a3735b90d21}
+
 # ImageBlockingPolicy.js
 component {f55f77f9-d33d-4759-82fc-60db3ee0bb91} ImageBlockingPolicy.js
 contract @mozilla.org/browser/blockimages-policy;1 {f55f77f9-d33d-4759-82fc-60db3ee0bb91}
 category content-policy ImageBlockingPolicy @mozilla.org/browser/blockimages-policy;1
 
 # XPIDialogService.js
 component {c1242012-27d8-477e-a0f1-0b098ffc329b} XPIDialogService.js
 contract @mozilla.org/addons/web-install-prompt;1 {c1242012-27d8-477e-a0f1-0b098ffc329b}
new file mode 100644
--- /dev/null
+++ b/mobile/android/components/PresentationRequestUIGlue.js
@@ -0,0 +1,86 @@
+/* -*- Mode: 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/. */
+
+"use strict"
+
+const { interfaces: Ci, utils: Cu, classes: Cc  } = Components;
+
+const TOPIC_PRESENTATION_RECEIVER_LAUNCH = "presentation-receiver:launch";
+const TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE = "presentation-receiver:launch:response";
+
+// globals XPCOMUtils
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+// globals Services
+Cu.import("resource://gre/modules/Services.jsm");
+
+function log(str) {
+  // dump("-*- PresentationRequestUIGlue.js -*-: " + str + "\n");
+}
+
+function PresentationRequestUIGlue() { }
+
+PresentationRequestUIGlue.prototype = {
+  sendRequest: function sendRequest(aURL, aSessionId, aDevice) {
+    log("PresentationRequestUIGlue - sendRequest aURL=" + aURL +
+        " aSessionId=" + aSessionId);
+
+    let localDevice;
+    try {
+      localDevice = aDevice.QueryInterface(Ci.nsIPresentationLocalDevice);
+    } catch (e) {
+      /* XXX: Currently, Fennec only support 1-UA devices. Remove this
+       * Promise.reject() when it starts to support 2-UA devices.
+       */
+      log("Not an 1-UA device.")
+      return new Promise.reject();
+    }
+
+    return new Promise((aResolve, aReject) => {
+
+      let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"]
+                            .getService(Ci.nsIUUIDGenerator);
+      let requestId = uuidGenerator.generateUUID().toString();
+
+      let handleObserve = (aSubject, aTopic, aData) => {
+        log("Got observe: aTopic=" + aTopic);
+
+        let data = JSON.parse(aData);
+        if (data.requestId != requestId) {
+          return;
+        }
+
+        Services.obs.removeObserver(handleObserve,
+                                    TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE);
+        switch(data.result) {
+          case "success":
+            aResolve(aSubject);
+            break;
+          case "error":
+            aReject();
+            break;
+        };
+      };
+
+      Services.obs.addObserver(handleObserve,
+                               TOPIC_PRESENTATION_RECEIVER_LAUNCH_RESPONSE,
+                               false);
+
+      let data = {
+        url: aURL,
+        windowId: localDevice.windowId,
+        requestId: requestId
+      };
+      Services.obs.notifyObservers(null,
+                                   TOPIC_PRESENTATION_RECEIVER_LAUNCH,
+                                   JSON.stringify(data));
+    })
+  },
+
+  classID: Components.ID("9c550ef7-3ff6-4bd1-9ad1-5a3735b90d21"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationRequestUIGlue])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationRequestUIGlue]);
--- a/mobile/android/components/moz.build
+++ b/mobile/android/components/moz.build
@@ -22,16 +22,17 @@ EXTRA_COMPONENTS += [
     'FilePicker.js',
     'FxAccountsPush.js',
     'HelperAppDialog.js',
     'ImageBlockingPolicy.js',
     'LoginManagerPrompter.js',
     'NSSDialogService.js',
     'PersistentNotificationHandler.js',
     'PresentationDevicePrompt.js',
+    'PresentationRequestUIGlue.js',
     'PromptService.js',
     'SessionStore.js',
     'SiteSpecificUserAgent.js',
     'Snippets.js',
     'TabSource.js',
     'XPIDialogService.js',
 ]
 
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -527,16 +527,17 @@
 @BINPATH@/components/FxAccountsPush.js
 @BINPATH@/components/HelperAppDialog.js
 @BINPATH@/components/LoginManagerPrompter.js
 @BINPATH@/components/MobileComponents.manifest
 @BINPATH@/components/MobileComponents.xpt
 @BINPATH@/components/NSSDialogService.js
 @BINPATH@/components/PersistentNotificationHandler.js
 @BINPATH@/components/PresentationDevicePrompt.js
+@BINPATH@/components/PresentationRequestUIGlue.js
 @BINPATH@/components/PromptService.js
 @BINPATH@/components/SessionStore.js
 @BINPATH@/components/SiteSpecificUserAgent.js
 @BINPATH@/components/Snippets.js
 
 @BINPATH@/components/XPIDialogService.js
 
 #ifdef ENABLE_MARIONETTE