Bug 788378 - Add guards to the AddonManager/AddonManagerInternal getters and setters, to ensure they're not used before startup/after shutdown. r=Mossop
authorBlair McBride <bmcbride@mozilla.com>
Tue, 18 Sep 2012 16:49:42 +1200
changeset 107353 9a02263d7206b21a69db33296291faa8e8f00347
parent 107247 93e7a6cb66fff69c204466ecf587299c9ba719da
child 107354 9b77800059a12fb5447054b76df7efe97b052879
push id23485
push userttaubert@mozilla.com
push dateWed, 19 Sep 2012 06:51:42 +0000
treeherdermozilla-central@80499f04e875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs788378
milestone18.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 788378 - Add guards to the AddonManager/AddonManagerInternal getters and setters, to ensure they're not used before startup/after shutdown. r=Mossop
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js
toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -1927,87 +1927,139 @@ var AddonManagerInternal = {
       if (this.typeListeners[pos] == aListener)
         this.typeListeners.splice(pos, 1);
       else
         pos++;
     }
   },
 
   get addonTypes() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return this.typesProxy;
   },
 
   get autoUpdateDefault() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gAutoUpdateDefault;
   },
 
   set autoUpdateDefault(aValue) {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     aValue = !!aValue;
     if (aValue != gAutoUpdateDefault)
       Services.prefs.setBoolPref(PREF_EM_AUTOUPDATE_DEFAULT, aValue);
     return aValue;
   },
 
   get checkCompatibility() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gCheckCompatibility;
   },
 
   set checkCompatibility(aValue) {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     aValue = !!aValue;
     if (aValue != gCheckCompatibility) {
       if (!aValue)
         Services.prefs.setBoolPref(PREF_EM_CHECK_COMPATIBILITY, false);
       else
         Services.prefs.clearUserPref(PREF_EM_CHECK_COMPATIBILITY);
     }
     return aValue;
   },
 
   get strictCompatibility() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gStrictCompatibility;
   },
 
   set strictCompatibility(aValue) {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     aValue = !!aValue;
     if (aValue != gStrictCompatibility)
       Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, aValue);
     return aValue;
   },
 
   get checkUpdateSecurityDefault() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gCheckUpdateSecurityDefault;
   },
 
   get checkUpdateSecurity() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gCheckUpdateSecurity;
   },
 
   set checkUpdateSecurity(aValue) {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     aValue = !!aValue;
     if (aValue != gCheckUpdateSecurity) {
       if (aValue != gCheckUpdateSecurityDefault)
         Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, aValue);
       else
         Services.prefs.clearUserPref(PREF_EM_CHECK_UPDATE_SECURITY);
     }
     return aValue;
   },
 
   get updateEnabled() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gUpdateEnabled;
   },
 
   set updateEnabled(aValue) {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     aValue = !!aValue;
     if (aValue != gUpdateEnabled)
       Services.prefs.setBoolPref(PREF_EM_UPDATE_ENABLED, aValue);
     return aValue;
   },
 
   get hotfixID() {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     return gHotfixID;
   },
 };
 
 /**
  * Should not be used outside of core Mozilla code. This is a private API for
  * the startup and platform integration code to use. Refer to the methods on
  * AddonManagerInternal for documentation however note that these methods are
@@ -2335,16 +2387,20 @@ var AddonManager = {
   /**
    * Determines whether an Addon should auto-update or not.
    *
    * @param  aAddon
    *         The Addon representing the add-on
    * @return true if the addon should auto-update, false otherwise.
    */
   shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
+    if (!gStarted)
+      throw Components.Exception("AddonManager is not initialized",
+                                 Cr.NS_ERROR_NOT_INITIALIZED);
+
     if (!aAddon || typeof aAddon != "object")
       throw Components.Exception("aAddon must be specified",
                                  Cr.NS_ERROR_INVALID_ARG);
     
     if (!("applyBackgroundUpdates" in aAddon))
       return false;
     if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
       return true;
--- a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js
@@ -1,60 +1,78 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Verify that API functions fail if the Add-ons Manager isn't initialised.
 
-const IGNORE = ["escapeAddonURI", "shouldAutoUpdate", "getStartupChanges",
-                "addTypeListener", "removeTypeListener",
-                "addAddonListener", "removeAddonListener",
-                "addInstallListener", "removeInstallListener",
-                "addManagerListener", "removeManagerListener"];
+const IGNORE = {
+  funcs: ["escapeAddonURI", "getStartupChanges", "addTypeListener",
+          "removeTypeListener", "addAddonListener", "removeAddonListener",
+          "addInstallListener", "removeInstallListener", "addManagerListener",
+          "removeManagerListener"],
+  getters: ["__AddonManagerInternal__"],
+  setters: []
+};
 
-const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride",
-                        "AddonScreenshot", "AddonType", "startup", "shutdown",
-                        "registerProvider", "unregisterProvider",
-                        "addStartupChange", "removeStartupChange"];
+const IGNORE_PRIVATE = {
+  funcs: ["AddonAuthor", "AddonCompatibilityOverride", "AddonScreenshot",
+          "AddonType", "startup", "shutdown", "registerProvider",
+          "unregisterProvider", "addStartupChange", "removeStartupChange"],
+  getters: [],
+  setters: []
+};
+
 
-function test_functions() {
-  for (let prop in AddonManager) {
-    if (typeof AddonManager[prop] != "function")
-      continue;
-    if (IGNORE.indexOf(prop) != -1)
-      continue;
+function test_functions(aObjName, aIgnore) {
+  let obj = this[aObjName];
+  for (let prop in obj) {
+    let desc = Object.getOwnPropertyDescriptor(obj, prop);
+
+    if (typeof desc.value == "function") {
+      if (aIgnore.funcs.indexOf(prop) != -1)
+        continue;
 
-    try {
-      do_print("AddonManager." + prop);
-      AddonManager[prop]();
-      do_throw(prop + " did not throw an exception");
-    }
-    catch (e) {
-      if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED)
-        do_throw(prop + " threw an unexpected exception: " + e);
-    }
-  }
-
-  for (let prop in AddonManagerPrivate) {
-    if (typeof AddonManagerPrivate[prop] != "function")
-      continue;
-    if (IGNORE_PRIVATE.indexOf(prop) != -1)
-      continue;
-
-    try {
-      do_print("AddonManagerPrivate." + prop);
-      AddonManagerPrivate[prop]();
-      do_throw(prop + " did not throw an exception");
-    }
-    catch (e) {
-      if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED)
-        do_throw(prop + " threw an unexpected exception: " + e);
+      try {
+        do_print(aObjName + "." + prop + "()");
+        obj[prop]();
+        do_throw(prop + " did not throw an exception");
+      }
+      catch (e) {
+        if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED)
+          do_throw(prop + " threw an unexpected exception: " + e);
+      }
+    } else {
+      if (typeof desc.get == "function" && aIgnore.getters.indexOf(prop) == -1) {
+        do_print(aObjName + "." + prop + " getter");
+        try {
+          let temp = obj[prop];
+          do_throw(prop + " did not throw an exception");
+        }
+        catch (e) {
+          if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED)
+            do_throw(prop + " threw an unexpected exception: " + e);
+        }
+      }
+      if (typeof desc.set == "function" && aIgnore.setters.indexOf(prop) == -1) {
+        do_print(aObjName + "." + prop + " setter");
+        try {
+          obj[prop] = "i am the walrus";
+          do_throw(prop + " did not throw an exception");
+        }
+        catch (e) {
+          if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED)
+            do_throw(prop + " threw an unexpected exception: " + e);
+        }
+      }
     }
   }
 }
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
-  test_functions();
+  test_functions("AddonManager", IGNORE);
+  test_functions("AddonManagerPrivate", IGNORE_PRIVATE);
   startupManager();
   shutdownManager();
-  test_functions();
+  test_functions("AddonManager", IGNORE);
+  test_functions("AddonManagerPrivate", IGNORE_PRIVATE);
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
@@ -13,16 +13,17 @@ function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
   // Create and configure the HTTP server.
   testserver = new HttpServer();
   testserver.registerDirectory("/data/", do_get_file("data"));
   testserver.start(4444);
 
   do_test_pending();
+  startupManager();
   run_test_1();
 }
 
 function end_test() {
   testserver.stop(do_test_finished);
 }
 
 // Test that a basic update check returns the expected available updates