Bug 1232105 - device prompt UI for presentation api; r=margaret
MozReview-Commit-ID: CdSe449XdwF
--- 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)