author | Gijs Kruitbosch <gijskruitbosch@gmail.com> |
Tue, 11 Mar 2014 00:35:53 +0000 | |
changeset 173118 | fdebf60103c313f6dde473e6c92818e07b6fba42 |
parent 173117 | 569c2bd2234e2e7d71813d7f7235b1c7df596e3b |
child 173119 | f8f0091f945c9e7767cb38dbee791a08766cc834 |
push id | 26391 |
push user | cbook@mozilla.com |
push date | Wed, 12 Mar 2014 11:20:34 +0000 |
treeherder | mozilla-central@a56837cfc67c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jaws |
bugs | 981418 |
milestone | 30.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
|
--- a/browser/components/customizableui/src/CustomizableUI.jsm +++ b/browser/components/customizableui/src/CustomizableUI.jsm @@ -1077,26 +1077,25 @@ let CustomizableUIInternal = { throw new Error("buildWidget was passed a non-widget to build."); } LOG("Building " + aWidget.id + " of type " + aWidget.type); let node; if (aWidget.type == "custom") { if (aWidget.onBuild) { - try { - node = aWidget.onBuild(aDocument); - } catch (ex) { - ERROR("Custom widget with id " + aWidget.id + " threw an error: " + ex.message); - } + node = aWidget.onBuild(aDocument); } if (!node || !(node instanceof aDocument.defaultView.XULElement)) ERROR("Custom widget with id " + aWidget.id + " does not return a valid node"); } else { + if (aWidget.onBeforeCreated) { + aWidget.onBeforeCreated(aDocument); + } node = aDocument.createElementNS(kNSXUL, "toolbarbutton"); node.setAttribute("id", aWidget.id); node.setAttribute("widget-id", aWidget.id); node.setAttribute("widget-type", aWidget.type); if (aWidget.disabled) { node.setAttribute("disabled", true); } @@ -1966,16 +1965,17 @@ let CustomizableUIInternal = { if ("type" in aData && gSupportedWidgetTypes.has(aData.type)) { widget.type = aData.type; } else { widget.type = "button"; } widget.disabled = aData.disabled === true; + this.wrapWidgetEventHandler("onBeforeCreated", widget); this.wrapWidgetEventHandler("onClick", widget); this.wrapWidgetEventHandler("onCreated", widget); if (widget.type == "button") { widget.onCommand = typeof aData.onCommand == "function" ? aData.onCommand : null; } else if (widget.type == "view") { @@ -2723,16 +2723,22 @@ this.CustomizableUI = { * 'custom' - for fine-grained control over the creation * of the widget. * - viewId: Only useful for views (and required there): the id of the * <panelview> that should be shown when clicking the widget. * - onBuild(aDoc): Only useful for custom widgets (and required there); a * function that will be invoked with the document in which * to build a widget. Should return the DOM node that has * been constructed. + * - onBeforeCreated(aDoc): Attached to all non-custom widgets; a function + * that will be invoked before the widget gets a DOM node + * constructed, passing the document in which that will happen. + * This is useful especially for 'view' type widgets that need + * to construct their views on the fly (e.g. from bootstrapped + * add-ons) * - onCreated(aNode): Attached to all widgets; a function that will be invoked * whenever the widget has a DOM node constructed, passing the * constructed node as an argument. * - onCommand(aEvt): Only useful for button widgets; a function that will be * invoked when the user activates the button. * - onClick(aEvt): Attached to all widgets; a function that will be invoked * when the user clicks the widget. * - onViewShowing(aEvt): Only useful for views; a function that will be
--- a/browser/components/customizableui/test/browser.ini +++ b/browser/components/customizableui/test/browser.ini @@ -69,9 +69,10 @@ skip-if = os == "linux" [browser_968565_insert_before_hidden_items.js] [browser_969427_recreate_destroyed_widget_after_reset.js] [browser_969661_character_encoding_navbar_disabled.js] [browser_970511_undo_restore_default.js] [browser_972267_customizationchange_events.js] [browser_973932_addonbar_currentset.js] [browser_975719_customtoolbars_behaviour.js] [browser_978084_dragEnd_after_move.js] +[browser_981418-widget-onbeforecreated-handler.js] [browser_panel_toggle.js]
new file mode 100644 --- /dev/null +++ b/browser/components/customizableui/test/browser_981418-widget-onbeforecreated-handler.js @@ -0,0 +1,90 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; +const kWidgetId = 'test-981418-widget-onbeforecreated'; + +// Should be able to add broken view widget +add_task(function testAddOnBeforeCreatedWidget() { + let viewShownDeferred = Promise.defer(); + let onBeforeCreatedCalled = false; + let widgetSpec = { + id: kWidgetId, + type: 'view', + viewId: kWidgetId + 'idontexistyet', + onBeforeCreated: function(doc) { + let view = doc.createElement("panelview"); + view.id = kWidgetId + 'idontexistyet'; + let label = doc.createElement("label"); + label.setAttribute("value", "Hello world"); + label.className = 'panel-subview-header'; + view.appendChild(label); + document.getElementById("PanelUI-multiView").appendChild(view); + onBeforeCreatedCalled = true; + }, + onViewShowing: function() { + viewShownDeferred.resolve(); + } + }; + + let noError = true; + try { + CustomizableUI.createWidget(widgetSpec); + CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_NAVBAR); + } catch (ex) { + Cu.reportError(ex); + noError = false; + } + ok(noError, "Should not throw an exception trying to add the widget."); + ok(onBeforeCreatedCalled, "onBeforeCreated should have been called"); + + let widgetNode = document.getElementById(kWidgetId); + ok(widgetNode, "Widget should exist"); + if (widgetNode) { + try { + widgetNode.click(); + + let shownTimeout = setTimeout(() => viewShownDeferred.reject("Panel not shown within 20s"), 20000); + yield viewShownDeferred.promise; + clearTimeout(shownTimeout); + ok(true, "Found view shown"); + + let tempPanel = document.getElementById("customizationui-widget-panel"); + let panelHiddenPromise = promisePanelElementHidden(window, tempPanel); + tempPanel.hidePopup(); + yield panelHiddenPromise; + + CustomizableUI.addWidgetToArea(kWidgetId, CustomizableUI.AREA_PANEL); + yield PanelUI.show(); + + viewShownDeferred = Promise.defer(); + widgetNode.click(); + + shownTimeout = setTimeout(() => viewShownDeferred.reject("Panel not shown within 20s"), 20000); + yield viewShownDeferred.promise; + clearTimeout(shownTimeout); + ok(true, "Found view shown"); + + let panelHidden = promisePanelHidden(window); + PanelUI.hide(); + yield panelHidden; + } catch (ex) { + ok(false, "Unexpected exception (like a timeout for one of the yields) " + + "when testing view widget."); + } + } + + noError = true; + try { + CustomizableUI.destroyWidget(kWidgetId); + } catch (ex) { + Cu.reportError(ex); + noError = false; + } + ok(noError, "Should not throw an exception trying to remove the broken view widget."); +}); + +add_task(function asyncCleanup() { + yield resetCustomization(); +});