Bug 1388724 - 6. Make WebrtcUI not depend on browser.js; r?esawin draft
authorJim Chen <nchen@mozilla.com>
Thu, 17 Aug 2017 20:21:32 -0400
changeset 648587 be8f087e1df21f8100df3fa4550a20b4371bd775
parent 648586 c1d37ad3998cb89945dec0e10e19293d2ebb7724
child 726864 46235df9bcbfb5c5c5316a26c322d9584cd51481
push id74801
push userbmo:nchen@mozilla.com
push dateFri, 18 Aug 2017 00:24:19 +0000
reviewersesawin
bugs1388724
milestone57.0a1
Bug 1388724 - 6. Make WebrtcUI not depend on browser.js; r?esawin Move WebrtcUI loading from browser.js to BrowserCLH.js, so that it can be loaded without GeckoApp/browser.js being active. Also use the universal doorhanger API to show the prompts. MozReview-Commit-ID: Gqsthvn7ZXA
mobile/android/chrome/content/WebrtcUI.js
mobile/android/chrome/content/browser.js
mobile/android/components/BrowserCLH.js
--- a/mobile/android/chrome/content/WebrtcUI.js
+++ b/mobile/android/chrome/content/WebrtcUI.js
@@ -1,19 +1,23 @@
 /* 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";
 
 this.EXPORTED_SYMBOLS = ["WebrtcUI"];
 
+XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService", "@mozilla.org/mediaManagerService;1", "nsIMediaManagerService");
 XPCOMUtils.defineLazyModuleGetter(this, "Notifications", "resource://gre/modules/Notifications.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "ParentalControls", "@mozilla.org/parental-controls-service;1", "nsIParentalControlsService");
 XPCOMUtils.defineLazyModuleGetter(this, "RuntimePermissions", "resource://gre/modules/RuntimePermissions.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "DoorHanger",
+                                  "resource://gre/modules/Prompt.jsm");
+
 var WebrtcUI = {
   _notificationId: null,
 
   // Add-ons can override stock permission behavior by doing:
   //
   //   var stockObserve = WebrtcUI.observe;
   //
   //   webrtcUI.observe = function(aSubject, aTopic, aData) {
@@ -128,17 +132,17 @@ var WebrtcUI = {
     let constraints = aSubject.getConstraints();
     let contentWindow = Services.wm.getOuterWindowWithId(aSubject.windowID);
 
     contentWindow.navigator.mozGetUserMediaDevices(
       constraints,
       function(devices) {
         if (!ParentalControls.isAllowed(ParentalControls.CAMERA_MICROPHONE)) {
           Services.obs.notifyObservers(null, "getUserMedia:response:deny", aSubject.callID);
-          WebrtcUI.showBlockMessage(devices);
+          WebrtcUI.showBlockMessage(contentWindow, devices);
           return;
         }
 
         WebrtcUI.prompt(contentWindow, aSubject.callID, constraints.audio,
                         constraints.video, devices);
       },
       function(error) {
         Cu.reportError(error);
@@ -238,17 +242,17 @@ var WebrtcUI = {
           label: Strings.browser.GetStringFromName("getUserMedia." + aType + ".prompt"),
           values: list
         });
 
       }
     }
   },
 
-  showBlockMessage: function(aDevices) {
+  showBlockMessage: function(aWindow, aDevices) {
     let microphone = false;
     let camera = false;
 
     for (let device of aDevices) {
       device = device.QueryInterface(Ci.nsIMediaDevice);
       if (device.type == "audio") {
         microphone = true;
       } else if (device.type == "video") {
@@ -260,17 +264,28 @@ var WebrtcUI = {
     if (microphone && !camera) {
       message = Strings.browser.GetStringFromName("getUserMedia.blockedMicrophoneAccess");
     } else if (camera && !microphone) {
       message = Strings.browser.GetStringFromName("getUserMedia.blockedCameraAccess");
     } else {
       message = Strings.browser.GetStringFromName("getUserMedia.blockedCameraAndMicrophoneAccess");
     }
 
-    NativeWindow.doorhanger.show(message, "webrtc-blocked", [], BrowserApp.selectedTab.id, {});
+    DoorHanger.show(aWindow, message, "webrtc-blocked");
+  },
+
+  getChromeWindow: function getChromeWindow(aWindow) {
+     let chromeWin = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIWebNavigation)
+                            .QueryInterface(Ci.nsIDocShellTreeItem)
+                            .rootTreeItem
+                            .QueryInterface(Ci.nsIInterfaceRequestor)
+                            .getInterface(Ci.nsIDOMWindow)
+                            .QueryInterface(Ci.nsIDOMChromeWindow);
+     return chromeWin;
   },
 
   prompt: function prompt(aContentWindow, aCallID, aAudioRequested,
                           aVideoRequested, aDevices) {
     let audioDevices = [];
     let videoDevices = [];
     for (let device of aDevices) {
       device = device.QueryInterface(Ci.nsIMediaDevice);
@@ -291,28 +306,30 @@ var WebrtcUI = {
       requestType = "CameraAndMicrophone";
     else if (audioDevices.length)
       requestType = "Microphone";
     else if (videoDevices.length)
       requestType = "Camera";
     else
       return;
 
+    let chromeWin = this.getChromeWindow(aContentWindow);
     let uri = aContentWindow.document.documentURIObject;
     let host = uri.host;
-    let requestor = BrowserApp.manifest ? "'" + BrowserApp.manifest.name + "'" : host;
+    let requestor = (chromeWin.BrowserApp && chromeWin.BrowserApp.manifest) ?
+          "'" + BrowserApp.manifest.name + "'" : host;
     let message = Strings.browser.formatStringFromName("getUserMedia.share" + requestType + ".message", [ requestor ], 1);
 
     let options = { inputs: [] };
     if (videoDevices.length > 1 || audioDevices.length > 0) {
       // videoSource is both the string used for l10n lookup and the object that will be returned
       this._addDevicesToOptions(videoDevices, "videoSource", options);
     }
 
     if (audioDevices.length > 1 || videoDevices.length > 0) {
       this._addDevicesToOptions(audioDevices, "audioDevice", options);
     }
 
     let buttons = this.getDeviceButtons(audioDevices, videoDevices, aCallID, uri);
 
-    NativeWindow.doorhanger.show(message, "webrtc-request", buttons, BrowserApp.selectedTab.id, options, "WEBRTC");
+    DoorHanger.show(aContentWindow, message, "webrtc-request", buttons, options, "WEBRTC");
   }
 }
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -148,26 +148,16 @@ lazilyLoadedBrowserScripts.forEach(funct
   });
 });
 
 var lazilyLoadedObserverScripts = [
   ["MemoryObserver", ["memory-pressure", "Memory:Dump"], "chrome://browser/content/MemoryObserver.js"],
   ["ConsoleAPI", ["console-api-log-event"], "chrome://browser/content/ConsoleAPI.js"],
 ];
 
-if (AppConstants.MOZ_WEBRTC) {
-  lazilyLoadedObserverScripts.push(
-    ["WebrtcUI", ["getUserMedia:ask-device-permission",
-                  "getUserMedia:request",
-                  "PeerConnection:request",
-                  "recording-device-events",
-                  "VideoCapture:Paused",
-                  "VideoCapture:Resumed"], "chrome://browser/content/WebrtcUI.js"])
-}
-
 lazilyLoadedObserverScripts.forEach(function (aScript) {
   let [name, notifications, script] = aScript;
   XPCOMUtils.defineLazyGetter(window, name, function() {
     let sandbox = {};
     Services.scriptloader.loadSubScript(script, sandbox);
     return sandbox[name];
   });
   let observer = (s, t, d) => {
@@ -278,21 +268,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
   "@mozilla.org/parental-controls-service;1", "nsIParentalControlsService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "DOMUtils",
   "@mozilla.org/inspector/dom-utils;1", "inIDOMUtils");
 
 XPCOMUtils.defineLazyServiceGetter(window, "URIFixup",
   "@mozilla.org/docshell/urifixup;1", "nsIURIFixup");
 
-if (AppConstants.MOZ_WEBRTC) {
-  XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
-    "@mozilla.org/mediaManagerService;1", "nsIMediaManagerService");
-}
-
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
   "resource://gre/modules/AndroidLog.jsm", "AndroidLog");
 
 // Define the "dump" function as a binding of the Log.d function so it specifies
 // the "debug" priority and a log tag.
 function dump(msg) {
   Log.d("Browser", msg);
 }
--- a/mobile/android/components/BrowserCLH.js
+++ b/mobile/android/components/BrowserCLH.js
@@ -4,16 +4,28 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
+                                  "resource://gre/modules/AppConstants.jsm");
+
+var Strings = {};
+
+XPCOMUtils.defineLazyGetter(Strings, "brand", _ =>
+        Services.strings.createBundle("chrome://branding/locale/brand.properties"));
+XPCOMUtils.defineLazyGetter(Strings, "browser", _ =>
+        Services.strings.createBundle("chrome://browser/locale/browser.properties"));
+XPCOMUtils.defineLazyGetter(Strings, "reader", _ =>
+        Services.strings.createBundle("chrome://global/locale/aboutReader.properties"));
+
 function BrowserCLH() {}
 
 BrowserCLH.prototype = {
   /**
    * Register resource://android as the APK root.
    *
    * Consumers can access Android assets using resource://android/assets/FILENAME.
    */
@@ -23,20 +35,52 @@ BrowserCLH.prototype = {
     let url = registry.convertChromeURL(Services.io.newURI("chrome://browser/content/aboutHome.xhtml")).spec;
     // Like jar:file:///data/app/org.mozilla.fennec-2.apk!/
     url = url.substring(4, url.indexOf("!/") + 2);
 
     let protocolHandler = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
     protocolHandler.setSubstitution("android", Services.io.newURI(url));
   },
 
+  addObserverScripts: function(aScripts) {
+    aScripts.forEach(item => {
+      let [name, notifications, script] = item;
+      XPCOMUtils.defineLazyGetter(this, name, _ => {
+        let sandbox = {};
+        Services.scriptloader.loadSubScript(script, sandbox);
+        return sandbox[name];
+      });
+      let observer = (s, t, d) => {
+        Services.obs.removeObserver(observer, t);
+        Services.obs.addObserver(this[name], t);
+        this[name].observe(s, t, d); // Explicitly notify new observer
+      };
+      notifications.forEach(notification => {
+        Services.obs.addObserver(observer, notification);
+      });
+    });
+  },
+
   observe: function(subject, topic, data) {
     switch (topic) {
       case "app-startup":
         this.setResourceSubstitutions();
+
+        let observerScripts = [];
+        if (AppConstants.MOZ_WEBRTC) {
+          observerScripts.push(["WebrtcUI", [
+            "getUserMedia:ask-device-permission",
+            "getUserMedia:request",
+            "PeerConnection:request",
+            "recording-device-events",
+            "VideoCapture:Paused",
+            "VideoCapture:Resumed",
+          ], "chrome://browser/content/WebrtcUI.js"]);
+        }
+        this.addObserverScripts(observerScripts);
         break;
     }
   },
 
   // QI
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
 
   // XPCOMUtils factory