Bug 844530 - Paper over error in BrowserElementPromptService.jsm on B2G. r=khuey
authorJustin Lebar <justin.lebar@gmail.com>
Wed, 27 Feb 2013 16:13:42 -0500
changeset 134496 7cdeee48963c6c466e8fb86b9c5c10e4dbefc480
parent 134495 2a33d38e3a1add83322d0b29dd2a0b148c5232e7
child 134497 56ee63cefc0b263004c0d0adbcf29a2497f0e924
push id336
push userakeybl@mozilla.com
push dateMon, 17 Jun 2013 22:53:19 +0000
treeherdermozilla-release@574a39cdf657 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs844530
milestone22.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 844530 - Paper over error in BrowserElementPromptService.jsm on B2G. r=khuey The error we're fixing is E/GeckoConsole( 397): [JavaScript Error: "NS_ERROR_FACTORY_NOT_REGISTERED: Component returned failure code: 0x80040154 (NS_ERROR_FACTORY_NOT_REGISTERED) [nsIComponentManager.getClassObject]" {file: "resource://gre/modules/BrowserElementPromptService.jsm" line: 572}] For some reason, we're running code before the vanilla prompt service is instantiated. We don't know why this is happening, but this patch works around the problem on B2G, which is the only place where we ship this code.
dom/browser-element/BrowserElementPromptService.jsm
--- a/dom/browser-element/BrowserElementPromptService.jsm
+++ b/dom/browser-element/BrowserElementPromptService.jsm
@@ -452,34 +452,26 @@ AuthPromptWrapper.prototype = {
       return true;
     } catch (e) {
       return false;
     }
   }
 };
 
 function BrowserElementPromptFactory(toWrap) {
+  // this._wrapped may be null.
   this._wrapped = toWrap;
 }
 
 BrowserElementPromptFactory.prototype = {
   classID: Components.ID("{24f3d0cf-e417-4b85-9017-c9ecf8bb1299}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIPromptFactory]),
 
-  _mayUseNativePrompt: function() {
-    try {
-      return Services.prefs.getBoolPref("browser.prompt.allowNative");
-    } catch (e) {
-      // This properity is default to true.
-      return true;
-    }
-  },
-
   _getNativePromptIfAllowed: function(win, iid, err) {
-    if (this._mayUseNativePrompt())
+    if (this._wrapped)
       return this._wrapped.getPrompt(win, iid);
     else {
       // Not allowed, throw an exception.
       throw err;
     }
   },
 
   getPrompt: function(win, iid) {
@@ -512,17 +504,17 @@ BrowserElementPromptFactory.prototype = 
         return new BrowserElementAuthPrompt().QueryInterface(iid);
       }
 
       // Because nsIAuthPrompt2 is called in parent process. If caller
       // wants nsIAuthPrompt2 and we cannot get BrowserElementchild,
       // it doesn't mean that we should fallback. It is possible that we can
       // get the BrowserElementParent from nsIChannel that passed to
       // functions of nsIAuthPrompt2.
-      if (this._mayUseNativePrompt()) {
+      if (this._wrapped) {
         return new AuthPromptWrapper(
             this._wrapped.getPrompt(win, iid),
             new BrowserElementAuthPrompt().QueryInterface(iid))
           .QueryInterface(iid);
       } else {
         // Falling back is not allowed, so we don't need wrap the
         // BrowserElementPrompt.
         return new BrowserElementAuthPrompt().QueryInterface(iid);
@@ -542,16 +534,25 @@ BrowserElementPromptFactory.prototype = 
 };
 
 this.BrowserElementPromptService = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
   _initialized: false,
 
+  _mayUseNativePrompt: function() {
+    try {
+      return Services.prefs.getBoolPref("browser.prompt.allowNative");
+    } catch (e) {
+      // This properity defaults to true.
+      return true;
+    }
+  },
+
   _init: function() {
     if (this._initialized) {
       return;
     }
 
     // If the pref is disabled, do nothing except wait for the pref to change.
     if (!this._browserFramesPrefEnabled()) {
       var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
@@ -560,31 +561,37 @@ this.BrowserElementPromptService = {
     }
 
     this._initialized = true;
     this._browserElementParentMap = new WeakMap();
 
     var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
     os.addObserver(this, "outer-window-destroyed", /* ownsWeak = */ true);
 
-    // Wrap the existing @mozilla.org/prompter;1 implementation.
-    var contractID = "@mozilla.org/prompter;1";
-    var oldCID = Cm.contractIDToCID(contractID);
+    var oldPromptFactory = null;
     var newCID = BrowserElementPromptFactory.prototype.classID;
-    var oldFactory = Cm.getClassObject(Cc[contractID], Ci.nsIFactory);
+    if (this._mayUseNativePrompt()) {
+      // Wrap the existing @mozilla.org/prompter;1 implementation.  (Don't even
+      // try to get the prompter;1 if we may not use the native prompter.  We
+      // won't need it, and merely getting it is causing bug 844530.)
+      var contractID = "@mozilla.org/prompter;1";
+      var oldCID = Cm.contractIDToCID(contractID);
+      var oldFactory = Cm.getClassObject(Cc[contractID], Ci.nsIFactory);
 
-    if (oldCID == newCID) {
-      debug("WARNING: Wrapped prompt factory is already installed!");
-      return;
+      if (oldCID == newCID) {
+        debug("WARNING: Wrapped prompt factory is already installed!");
+        return;
+      }
+
+      Cm.unregisterFactory(oldCID, oldFactory);
+
+      oldPromptFactory = oldFactory.createInstance(null, Ci.nsIPromptFactory);
     }
 
-    Cm.unregisterFactory(oldCID, oldFactory);
-
-    var oldInstance = oldFactory.createInstance(null, Ci.nsIPromptFactory);
-    var newInstance = new BrowserElementPromptFactory(oldInstance);
+    var newInstance = new BrowserElementPromptFactory(oldPromptFactory);
 
     var newFactory = {
       createInstance: function(outer, iid) {
         if (outer != null) {
           throw Cr.NS_ERROR_NO_AGGREGATION;
         }
         return newInstance.QueryInterface(iid);
       }