Bug 1232105 - device prompt UI for presentation api; r=margaret draft
authorChun-Min Chang <chun.m.chang@gmail.com>
Mon, 25 Apr 2016 11:34:23 +0800
changeset 355737 c97049c19924f22abea863b5d990ba24d3d01c45
parent 354481 4feb4dd910a5a2d3061dbdd376a80975206819c6
child 519270 cfa4bea53f72a3aca5b82fd826831b94d46acd0f
push id16370
push userbmo:cchang@mozilla.com
push dateMon, 25 Apr 2016 03:35:26 +0000
reviewersmargaret
bugs1232105
milestone48.0a1
Bug 1232105 - device prompt UI for presentation api; r=margaret MozReview-Commit-ID: CdSe449XdwF
mobile/android/components/MobileComponents.manifest
mobile/android/components/PresentationDevicePrompt.js
mobile/android/components/moz.build
mobile/android/installer/package-manifest.in
mobile/android/locales/en-US/chrome/devicePrompt.properties
mobile/android/locales/jar.mn
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -39,16 +39,20 @@ contract @mozilla.org/content-permission
 
 # PromptService.js
 component {9a61149b-2276-4a0a-b79c-be994ad106cf} PromptService.js
 contract @mozilla.org/prompter;1 {9a61149b-2276-4a0a-b79c-be994ad106cf}
 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}
+
 # 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/PresentationDevicePrompt.js
@@ -0,0 +1,132 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* 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 } = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+XPCOMUtils.defineLazyModuleGetter(this, "Prompt",
+                                  "resource://gre/modules/Prompt.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
+                                  "resource://gre/modules/UITelemetry.jsm");
+
+const kPRESENTATIONDEVICEPROMPT_CONTRACTID = "@mozilla.org/presentation-device/prompt;1";
+const kPRESENTATIONDEVICEPROMPT_CID        = Components.ID("{388bd149-c919-4a43-b646-d7ec57877689}");
+
+function debug(aMsg) {
+  // dump("-*- PresentationDevicePrompt: " + aMsg + "\n");
+}
+
+// nsIPresentationDevicePrompt
+function PresentationDevicePrompt() {
+  debug("PresentationDevicePrompt init");
+}
+
+PresentationDevicePrompt.prototype = {
+  classID: kPRESENTATIONDEVICEPROMPT_CID,
+  contractID: kPRESENTATIONDEVICEPROMPT_CONTRACTID,
+  classDescription: "Fennec Presentation Device Prompt",
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevicePrompt]),
+
+  _devices: [],   // Store all available presentation devices
+  _request: null, // Store the request from presentation api
+
+  _getString: function(aName) {
+    debug("_getString");
+
+    if (!this.bundle) {
+      this.bundle = Services.strings.createBundle("chrome://browser/locale/devicePrompt.properties");
+    }
+    return this.bundle.GetStringFromName(aName);
+  },
+
+  _loadDevices: function() {
+    debug("_loadDevices");
+
+    let deviceManager = Cc["@mozilla.org/presentation-device/manager;1"]
+                          .getService(Ci.nsIPresentationDeviceManager);
+    let devices = deviceManager.getAvailableDevices().QueryInterface(Ci.nsIArray);
+
+    // Re-load the available devices
+    this._devices = [];
+    for (let i = 0; i < devices.length; i++) {
+      let device = devices.queryElementAt(i, Ci.nsIPresentationDevice);
+      this._devices.push(device);
+    }
+  },
+
+  _getPromptMenu: function(aDevices) {
+    debug("_getPromptMenu");
+
+    return aDevices.map(function(device) {
+      return { label: device.name };
+    });
+  },
+
+  _getPrompt: function(aTitle, aMenu) {
+    debug("_getPrompt");
+
+    let p = new Prompt({
+      title: aTitle,
+    });
+
+    p.setSingleChoiceItems(aMenu);
+
+    return p;
+  },
+
+  _showPrompt: function(aPrompt, aCallback) {
+    debug("_showPrompt");
+
+    aPrompt.show(function(data) {
+      let buttonIndex = data.button;
+      aCallback(buttonIndex);
+    });
+  },
+
+  _selectDevice: function(aIndex) {
+    debug("_selectDevice");
+
+    if (!this._request) {
+      return;
+    }
+
+    if (aIndex < 0 ||             // Cancel request if no selected device,
+        !this._devices.length) {  // or there is no available devices
+      this._request.cancel();
+      return;
+    }
+
+    this._request.select(this._devices[aIndex]);
+  },
+
+  // This will be fired when window.PresentationRequest(URL).start() is called
+  promptDeviceSelection: function(aRequest) {
+    debug("promptDeviceSelection");
+
+    // Load available presentation devices into this._devices
+    this._loadDevices();
+
+    if (!this._devices.length) { // Cancel request if no available device
+      aRequest.cancel();
+      return;
+    }
+
+    this._request = aRequest;
+
+    let prompt = this._getPrompt(this._getString("deviceMenu.title"),
+                                 this._getPromptMenu(this._devices));
+
+    this._showPrompt(prompt, this._selectDevice.bind(this));
+
+    UITelemetry.addEvent("show.1", "dialog", null, "prompt_device_selection");
+  },
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PresentationDevicePrompt]);
--- a/mobile/android/components/moz.build
+++ b/mobile/android/components/moz.build
@@ -20,16 +20,17 @@ EXTRA_COMPONENTS += [
     'ContentDispatchChooser.js',
     'ContentPermissionPrompt.js',
     'DirectoryProvider.js',
     'FilePicker.js',
     'HelperAppDialog.js',
     'ImageBlockingPolicy.js',
     'LoginManagerPrompter.js',
     'NSSDialogService.js',
+    'PresentationDevicePrompt.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
@@ -536,16 +536,17 @@
 @BINPATH@/components/ImageBlockingPolicy.js
 @BINPATH@/components/DirectoryProvider.js
 @BINPATH@/components/FilePicker.js
 @BINPATH@/components/HelperAppDialog.js
 @BINPATH@/components/LoginManagerPrompter.js
 @BINPATH@/components/MobileComponents.manifest
 @BINPATH@/components/MobileComponents.xpt
 @BINPATH@/components/NSSDialogService.js
+@BINPATH@/components/PresentationDevicePrompt.js
 @BINPATH@/components/PromptService.js
 @BINPATH@/components/SessionStore.js
 @BINPATH@/components/SiteSpecificUserAgent.js
 @BINPATH@/components/Snippets.js
 
 @BINPATH@/components/XPIDialogService.js
 
 #ifdef ENABLE_MARIONETTE
new file mode 100644
--- /dev/null
+++ b/mobile/android/locales/en-US/chrome/devicePrompt.properties
@@ -0,0 +1,1 @@
+deviceMenu.title=Nearby Devices
--- a/mobile/android/locales/jar.mn
+++ b/mobile/android/locales/jar.mn
@@ -21,16 +21,17 @@
   locale/@AB_CD@/browser/aboutHealthReport.dtd    (%chrome/aboutHealthReport.dtd)
 #endif
   locale/@AB_CD@/browser/browser.properties       (%chrome/browser.properties)
   locale/@AB_CD@/browser/config.dtd               (%chrome/config.dtd)
   locale/@AB_CD@/browser/config.properties        (%chrome/config.properties)
   locale/@AB_CD@/browser/localepicker.properties  (%chrome/localepicker.properties)
   locale/@AB_CD@/browser/checkbox.dtd             (%chrome/checkbox.dtd)
   locale/@AB_CD@/browser/notification.dtd         (%chrome/notification.dtd)
+  locale/@AB_CD@/browser/devicePrompt.properties  (%chrome/devicePrompt.properties)
   locale/@AB_CD@/browser/pippki.properties        (%chrome/pippki.properties)
   locale/@AB_CD@/browser/sync.dtd                 (%chrome/sync.dtd)
   locale/@AB_CD@/browser/sync.properties          (%chrome/sync.properties)
   locale/@AB_CD@/browser/prompt.dtd               (%chrome/prompt.dtd)
   locale/@AB_CD@/browser/feedback.dtd             (%chrome/feedback.dtd)
   locale/@AB_CD@/browser/phishing.dtd             (%chrome/phishing.dtd)
   locale/@AB_CD@/browser/handling.properties      (%chrome/handling.properties)
   locale/@AB_CD@/browser/aboutLogins.dtd          (%chrome/aboutLogins.dtd)