Bug 988305 - UITour: getTarget should catch exceptions from a target's query function. r=Unfocused a=Sylvestre
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Sat, 29 Mar 2014 18:41:35 -0700
changeset 192421 74d94bd2db30e2d38120e8e15c2ba5ec190b3427
parent 192420 a051669b62ea522fc90c3c88f7671a8943f6c166
child 192422 e1b7b7176710fdc0c0f7e2835afaf1f26d627231
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersUnfocused, Sylvestre
bugs988305
milestone30.0a2
Bug 988305 - UITour: getTarget should catch exceptions from a target's query function. r=Unfocused a=Sylvestre
browser/modules/UITour.jsm
browser/modules/test/browser_UITour_availableTargets.js
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -678,30 +678,30 @@ this.UITour = {
     let targetObject = this.targets.get(aTargetName);
     if (!targetObject) {
       deferred.reject("The specified target name is not in the allowed set");
       return deferred.promise;
     }
 
     let targetQuery = targetObject.query;
     aWindow.PanelUI.ensureReady().then(() => {
+      let node;
       if (typeof targetQuery == "function") {
-        deferred.resolve({
-          addTargetListener: targetObject.addTargetListener,
-          node: targetQuery(aWindow.document),
-          removeTargetListener: targetObject.removeTargetListener,
-          targetName: aTargetName,
-          widgetName: targetObject.widgetName,
-        });
-        return;
+        try {
+          node = targetQuery(aWindow.document);
+        } catch (ex) {
+          node = null;
+        }
+      } else {
+        node = aWindow.document.querySelector(targetQuery);
       }
 
       deferred.resolve({
         addTargetListener: targetObject.addTargetListener,
-        node: aWindow.document.querySelector(targetQuery),
+        node: node,
         removeTargetListener: targetObject.removeTargetListener,
         targetName: aTargetName,
         widgetName: targetObject.widgetName,
       });
     }).then(null, Cu.reportError);
     return deferred.promise;
   },
 
--- a/browser/modules/test/browser_UITour_availableTargets.js
+++ b/browser/modules/test/browser_UITour_availableTargets.js
@@ -59,16 +59,40 @@ let tests = [
       ok(UITour.availableTargetsCache.has(window),
          "Targets should now be cached again");
       CustomizableUI.reset();
       ok(!UITour.availableTargetsCache.has(window),
          "Targets should not be cached after reset");
       done();
     });
   },
+
+  function test_availableTargets_exceptionFromGetTarget(done) {
+    // The query function for the "search" target will throw if it's not found.
+    // Make sure the callback still fires with the other available targets.
+    CustomizableUI.removeWidgetFromArea("search-container");
+    gContentAPI.getConfiguration("availableTargets", (data) => {
+      // Default minus "search" and "searchProvider"
+      ok_targets(data, [
+        "accountStatus",
+        "addons",
+        "appMenu",
+        "backForward",
+        "bookmarks",
+        "customize",
+        "help",
+        "home",
+        "pinnedTab",
+        "quit",
+        "urlbar",
+      ]);
+      CustomizableUI.reset();
+      done();
+    });
+  },
 ];
 
 function ok_targets(actualData, expectedTargets) {
   // Depending on how soon after page load this is called, the selected tab icon
   // may or may not be showing the loading throbber.  Check for its presence and
   // insert it into expectedTargets if it's visible.
   let selectedTabIcon =
     document.getAnonymousElementByAttribute(gBrowser.selectedTab,