Bug 684727 - Don't call into JNI from ExtensionsView.init [r=mbrubeck]
authorMark Finkle <mfinkle@mozilla.com>
Wed, 07 Sep 2011 10:48:11 -0400
changeset 77981 1ddde977131ab1245e0d6e209cf75b3bc4b70553
parent 77980 b221c62a19c353c8c50cceed82da2dab0982a379
child 77982 ac5813b1196e5ec0d04152894a1fc4dab046cb31
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs684727
milestone9.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 684727 - Don't call into JNI from ExtensionsView.init [r=mbrubeck]
mobile/chrome/content/extensions.js
mobile/components/BrowserStartup.js
mobile/components/Makefile.in
--- a/mobile/chrome/content/extensions.js
+++ b/mobile/chrome/content/extensions.js
@@ -216,27 +216,16 @@ var ExtensionsView = {
 
     this._dloadmgr = new AddonInstallListener();
     AddonManager.addInstallListener(this._dloadmgr);
 
     // Watch for add-on update notifications
     let os = Services.obs;
     os.addObserver(this, "addon-update-started", false);
     os.addObserver(this, "addon-update-ended", false);
-
-    if (!Services.prefs.getBoolPref("extensions.hideUpdateButton"))
-      document.getElementById("addons-update-all").hidden = false;
-
-#ifdef ANDROID
-    // Hide the notification
-    let alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
-    let progressListener = alertsService.QueryInterface(Ci.nsIAlertsProgressListener);
-    if (progressListener)
-      progressListener.onCancel(ADDONS_NOTIFICATION_NAME);
-#endif
   },
 
   delayedInit: function ev__delayedInit() {
     if (this._list)
       return;
 
     this.init(); // In case the panel is selected before init has been called.
 
@@ -254,29 +243,34 @@ var ExtensionsView = {
     }
 
     let strings = Strings.browser;
     this._strings["addonType.extension"] = strings.GetStringFromName("addonType.2");
     this._strings["addonType.theme"] = strings.GetStringFromName("addonType.4");
     this._strings["addonType.locale"] = strings.GetStringFromName("addonType.8");
     this._strings["addonType.search"] = strings.GetStringFromName("addonType.1024");
 
+    if (!Services.prefs.getBoolPref("extensions.hideUpdateButton"))
+      document.getElementById("addons-update-all").hidden = false;
+
     let self = this;
     setTimeout(function() {
       self.getAddonsFromLocal();
       self.getAddonsFromRepo("");
     }, 0);
   },
 
   uninit: function ev_uninit() {
     let os = Services.obs;
     os.removeObserver(this, "addon-update-started");
     os.removeObserver(this, "addon-update-ended");
 
     AddonManager.removeInstallListener(this._dloadmgr);
+
+    this.hideAlerts();
   },
 
   hideOnSelect: function ev_handleEvent(aEvent) {
     // When list selection changes, be sure to close up any open options sections
     if (aEvent.target == this._list)
       this.hideOptions();
   },
 
@@ -835,26 +829,34 @@ var ExtensionsView = {
       else
         toaster.showAlertNotification(image, strings.GetStringFromName("alertAddons"), aMessage, true, "", observer);
     } else {
       // Only show an alert for a normal add-on if the manager is not visible
       if (!this.visible) {
         let alerts = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
         alerts.showAlertNotification(URI_GENERIC_ICON_XPINSTALL, strings.GetStringFromName("alertAddons"),
                                      aMessage, true, "", observer, ADDONS_NOTIFICATION_NAME);
+
+        // Use a preference to help us cleanup this notification in case we don't shutdown correctly
+        Services.prefs.setBoolPref("browser.notifications.pending.addons", true);
+        Services.prefs.savePrefFile(null);
       }
     }
   },
 
   hideAlerts: function ev_hideAlerts() {
 #ifdef ANDROID
     let alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
     let progressListener = alertsService.QueryInterface(Ci.nsIAlertsProgressListener);
-    progressListener.onCancel(ADDONS_NOTIFICATION_NAME);
+    if (progressListener)
+      progressListener.onCancel(ADDONS_NOTIFICATION_NAME);
 #endif
+
+    // Keep our preference in sync
+    Services.prefs.clearUserPref("browser.notifications.pending.addons");
   },
 };
 
 
 function searchFailed() {
   ExtensionsView.clearSection("repo");
 
   let strings = Strings.browser;
@@ -994,18 +996,20 @@ AddonInstallListener.prototype = {
   },
 
   onDownloadProgress: function xpidm_onDownloadProgress(aInstall) {
     let element = ExtensionsView.getElementForAddon(aInstall.sourceURI.spec);
 
 #ifdef ANDROID
     let alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
     let progressListener = alertsService.QueryInterface(Ci.nsIAlertsProgressListener);
-    progressListener.onProgress(ADDONS_NOTIFICATION_NAME, aInstall.progress, aInstall.maxProgress);
+    if (progressListener)
+      progressListener.onProgress(ADDONS_NOTIFICATION_NAME, aInstall.progress, aInstall.maxProgress);
 #endif
+
     if (!element)
       return;
 
     let opType = element.getAttribute("opType");
     if (!opType)
       element.setAttribute("opType", "needs-install");
 
     let progress = Math.round((aInstall.progress / aInstall.maxProgress) * 100);
--- a/mobile/components/BrowserStartup.js
+++ b/mobile/components/BrowserStartup.js
@@ -33,16 +33,19 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 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");
+
+const ADDONS_NOTIFICATION_NAME = "addons";
 
 // Custom factory object to ensure that we're a singleton
 const BrowserStartupServiceFactory = {
   _instance: null,
   createInstance: function (outer, iid) {
     if (outer != null)
       throw Components.results.NS_ERROR_NO_AGGREGATION;
     return this._instance || (this._instance = new BrowserStartup());
@@ -50,29 +53,28 @@ const BrowserStartupServiceFactory = {
 };
 
 function BrowserStartup() {
   this._init();
 }
 
 BrowserStartup.prototype = {
   // for XPCOM
-  classID:          Components.ID("{1d542abc-c88b-4636-a4ef-075b49806317}"),
+  classID: Components.ID("{1d542abc-c88b-4636-a4ef-075b49806317}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
   _xpcom_factory: BrowserStartupServiceFactory,
 
-  _init: function () {
-    this._observerService = Cc["@mozilla.org/observer-service;1"].
-                            getService(Ci.nsIObserverService);
-    this._observerService.addObserver(this, "places-init-complete", false);
+  _init: function() {
+    Services.obs.addObserver(this, "places-init-complete", false);
+    Services.obs.addObserver(this, "final-ui-startup", false);
   },
 
-  _initDefaultBookmarks: function () {
+  _initDefaultBookmarks: function() {
     // We must instantiate the history service since it will tell us if we
     // need to import or restore bookmarks due to first-run, corruption or
     // forced migration (due to a major schema change).
     let histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
                   getService(Ci.nsINavHistoryService);
 
     // If the database is corrupt or has been newly created we should
     // import bookmarks.
@@ -123,20 +125,39 @@ BrowserStartup.prototype = {
       sl.init(observer);
       channel.asyncOpen(sl, channel);
     } catch (err) {
       // Report the error, but ignore it.
       Cu.reportError("Failed to load default bookmarks from bookmarks.json: " + err);
     }
   },
 
+  _startupActions: function() {
+#ifdef ANDROID
+    // Hide the notification if we had any pending operations
+    try {
+      if (Services.prefs.getBoolPref("browser.notifications.pending.addons")) {
+        Services.prefs.clearUserPref("browser.notifications.pending.addons")
+        let alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
+        let progressListener = alertsService.QueryInterface(Ci.nsIAlertsProgressListener);
+        if (progressListener)
+          progressListener.onCancel(ADDONS_NOTIFICATION_NAME);
+      }
+    } catch (e) {}
+#endif
+  },
+
   // nsIObserver
   observe: function(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "places-init-complete":
+        Services.obs.removeObserver(this, "places-init-complete");
         this._initDefaultBookmarks();
-        this._observerService.removeObserver(this, "places-init-complete");
+        break;
+      case "final-ui-startup":
+        Services.obs.removeObserver(this, "final-ui-startup");
+        this._startupActions();
         break;
     }
   }
 };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([BrowserStartup]);
--- a/mobile/components/Makefile.in
+++ b/mobile/components/Makefile.in
@@ -51,25 +51,25 @@ XPIDLSRCS = \
         LoginManagerPrompter.idl \
         WebappsSupport.idl \
         $(NULL)
 
 EXTRA_PP_COMPONENTS = \
         MobileComponents.manifest \
         AboutRedirector.js \
         BrowserCLH.js \
+        BrowserStartup.js \
         DirectoryProvider.js\
         HelperAppDialog.js \
         Sidebar.js \
         SessionStore.js \
         $(NULL)
 
 EXTRA_COMPONENTS = \
         AlertsService.js \
-        BrowserStartup.js \
         ContentPermissionPrompt.js \
         XPIDialogService.js \
         DownloadManagerUI.js \
         PromptService.js \
         ContentDispatchChooser.js \
         AutoCompleteCache.js \
         AddonUpdateService.js \
         FormAutoComplete.js \