Bug 844530 - Paper over error in BrowserElementPromptService.jsm on B2G. r=khuey
☠☠ backed out by 58c7e618c860 ☠ ☠
authorJustin Lebar <justin.lebar@gmail.com>
Wed, 27 Feb 2013 14:39:57 -0500
changeset 123203 b7473553fea140debdd7574cd9d174b0507e9ab6
parent 123202 7a79ddc7bedf213d15b67f052c7bb06d36fd275d
child 123204 a87453b34058710274990a26b0cecce1897eab4d
push id24373
push userryanvm@gmail.com
push dateThu, 28 Feb 2013 01:36:21 +0000
treeherdermozilla-central@8cb9d6981978 [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 newCID = BrowserElementPromptFactory.prototype.classID;
-    var oldFactory = Cm.getClassObject(Cc[contractID], Ci.nsIFactory);
+    var oldPromptFactory = null;
+    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 newCID = BrowserElementPromptFactory.prototype.classID;
+      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);
       }