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 76670 1ddde977131ab1245e0d6e209cf75b3bc4b70553
parent 76669 b221c62a19c353c8c50cceed82da2dab0982a379
child 76671 ac5813b1196e5ec0d04152894a1fc4dab046cb31
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersmbrubeck
bugs684727
milestone9.0a1
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 \