From f20e680972c7b0ba30bc1694b67997395cd6e9e6 Mon Sep 17 00:00:00 2001 From: Mike Conley Date: Wed, 2 Apr 2014 16:39:00 -0400 Subject: [PATCH] Bug 989609 - Dynamically added toolbars with API-created widgets should not break customize mode. r=Unfocused,mdeboer --- .../customizableui/src/CustomizableUI.jsm | 29 ++++--- .../customizableui/test/browser.ini | 1 + ...wser_989609_bootstrapped_custom_toolbar.js | 75 +++++++++++++++++++ 3 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 browser/components/customizableui/test/browser_989609_bootstrapped_custom_toolbar.js diff --git a/browser/components/customizableui/src/CustomizableUI.jsm b/browser/components/customizableui/src/CustomizableUI.jsm index c9f296001e8c..19a2b791763b 100644 --- a/browser/components/customizableui/src/CustomizableUI.jsm +++ b/browser/components/customizableui/src/CustomizableUI.jsm @@ -1594,6 +1594,12 @@ let CustomizableUIInternal = { aPosition = placements.length; } + let widget = gPalette.get(aWidgetId); + if (widget) { + widget.currentPosition = aPosition; + widget.currentArea = oldPlacement.area; + } + if (aPosition == oldPlacement.position) { return; } @@ -1606,11 +1612,6 @@ let CustomizableUIInternal = { } placements.splice(aPosition, 0, aWidgetId); - let widget = gPalette.get(aWidgetId); - if (widget) { - widget.currentPosition = aPosition; - } - gDirty = true; gDirtyAreaCache.add(oldPlacement.area); @@ -1656,19 +1657,25 @@ let CustomizableUIInternal = { }, restoreStateForArea: function(aArea, aLegacyState) { - if (gPlacements.has(aArea)) { - // Already restored. - return; - } + let placementsPreexisted = gPlacements.has(aArea); this.beginBatchUpdate(); try { gRestoring = true; let restored = false; - gPlacements.set(aArea, []); + if (placementsPreexisted) { + LOG("Restoring " + aArea + " from pre-existing placements"); + for (let [position, id] in Iterator(gPlacements.get(aArea))) { + this.moveWidgetWithinArea(id, position); + } + gDirty = false; + restored = true; + } else { + gPlacements.set(aArea, []); + } - if (gSavedState && aArea in gSavedState.placements) { + if (!restored && gSavedState && aArea in gSavedState.placements) { LOG("Restoring " + aArea + " from saved state"); let placements = gSavedState.placements[aArea]; for (let id of placements) diff --git a/browser/components/customizableui/test/browser.ini b/browser/components/customizableui/test/browser.ini index 8f3e00125264..ab912db5bfdd 100644 --- a/browser/components/customizableui/test/browser.ini +++ b/browser/components/customizableui/test/browser.ini @@ -95,6 +95,7 @@ skip-if = os == "linux" [browser_981418-widget-onbeforecreated-handler.js] [browser_985815_propagate_setToolbarVisibility.js] [browser_981305_separator_insertion.js] +[browser_989609_bootstrapped_custom_toolbar.js] [browser_987177_destroyWidget_xul.js] [browser_987177_xul_wrapper_updating.js] [browser_987492_window_api.js] diff --git a/browser/components/customizableui/test/browser_989609_bootstrapped_custom_toolbar.js b/browser/components/customizableui/test/browser_989609_bootstrapped_custom_toolbar.js new file mode 100644 index 000000000000..18d038accf5b --- /dev/null +++ b/browser/components/customizableui/test/browser_989609_bootstrapped_custom_toolbar.js @@ -0,0 +1,75 @@ +/* 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 kTestBarID = "testBar"; +const kWidgetID = "characterencoding-button"; + +function createTestBar() { + let testBar = document.createElement("toolbar"); + testBar.id = kTestBarID; + testBar.setAttribute("customizable", "true"); + CustomizableUI.registerArea(kTestBarID, + { type: CustomizableUI.TYPE_TOOLBAR, legacy: false } + ); + gNavToolbox.appendChild(testBar); + return testBar; +} + +/** + * Helper function that does the following: + * + * 1) Creates a custom toolbar and registers it + * with CustomizableUI. + * 2) Adds the widget with ID aWidgetID to that new + * toolbar. + * 3) Enters customize mode and makes sure that the + * widget is still in the right toolbar. + * 4) Exits customize mode, then removes and deregisters + * the custom toolbar. + * 5) Checks that the widget has no placement. + * 6) Re-adds and re-registers a custom toolbar with the same + * ID as the first one. + * 7) Enters customize mode and checks that the widget is + * properly back in the toolbar. + * 8) Exits customize mode, removes and de-registers the + * toolbar, and resets the toolbars to default. + */ +function checkRestoredPresence(aWidgetID) { + return Task.spawn(function* () { + let testBar = createTestBar(); + CustomizableUI.addWidgetToArea(aWidgetID, kTestBarID); + let placement = CustomizableUI.getPlacementOfWidget(aWidgetID); + is(placement.area, kTestBarID, + "Expected " + aWidgetID + " to be in the test toolbar"); + + CustomizableUI.unregisterArea(testBar.id); + testBar.remove(); + + let placement = CustomizableUI.getPlacementOfWidget(aWidgetID); + is(placement, null, "Expected " + aWidgetID + " to be in the palette"); + + testBar = createTestBar(); + + yield startCustomizing(); + let placement = CustomizableUI.getPlacementOfWidget(aWidgetID); + is(placement.area, kTestBarID, + "Expected " + aWidgetID + " to be in the test toolbar"); + yield endCustomizing(); + + CustomizableUI.unregisterArea(testBar.id); + testBar.remove(); + + yield resetCustomization(); + }); +} + +add_task(function* () { + yield checkRestoredPresence("downloads-button") +}); + +add_task(function* () { + yield checkRestoredPresence("characterencoding-button") +}); \ No newline at end of file