Bug 1397447 - make downloads button autohide by default, r=mak
MozReview-Commit-ID: E9izQpa4fFZ
This commit is contained in:
@@ -368,6 +368,10 @@ pref("browser.download.animateNotifications", true);
|
||||
// This records whether or not the panel has been shown at least once.
|
||||
pref("browser.download.panel.shown", false);
|
||||
|
||||
// This controls whether the button is automatically shown/hidden depending
|
||||
// on whether there are downloads to show.
|
||||
pref("browser.download.autohideButton", true);
|
||||
|
||||
#ifndef XP_MACOSX
|
||||
pref("browser.helperApps.deleteTempFileOnExit", true);
|
||||
#endif
|
||||
|
||||
@@ -39,7 +39,6 @@ var CustomizationHandler = {
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
PlacesToolbarHelper.customizeStart();
|
||||
DownloadsButton.customizeStart();
|
||||
},
|
||||
|
||||
_customizationEnding(aDetails) {
|
||||
@@ -63,7 +62,6 @@ var CustomizationHandler = {
|
||||
}
|
||||
|
||||
PlacesToolbarHelper.customizeDone();
|
||||
DownloadsButton.customizeDone();
|
||||
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
|
||||
@@ -518,10 +518,9 @@ toolbar:not(#TabsToolbar) > #personal-bookmarks {
|
||||
|
||||
/* ::::: location bar & search bar ::::: */
|
||||
|
||||
#urlbar-container {
|
||||
min-width: 50ch;
|
||||
}
|
||||
|
||||
/* url bar min-width is defined further down, together with the maximum size
|
||||
* of the identity icon block, for different window sizes.
|
||||
*/
|
||||
#search-container {
|
||||
min-width: 25ch;
|
||||
}
|
||||
@@ -701,41 +700,69 @@ html|input.urlbar-input[textoverflow]:not([focused]) {
|
||||
-moz-user-focus: ignore;
|
||||
}
|
||||
|
||||
|
||||
/* We leave 49ch plus whatever space the download button will need when it
|
||||
* appears. Normally this should be 16px for the icon, plus 2 * 2px padding
|
||||
* plus the toolbarbutton-inner-padding. We're adding 4px to ensure things
|
||||
* like rounding on hidpi don't accidentally result in the button going
|
||||
* into overflow.
|
||||
*/
|
||||
#urlbar-container {
|
||||
min-width: calc(49ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 49ch;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
max-width: 18em;
|
||||
max-width: 17em;
|
||||
}
|
||||
@media (max-width: 700px) {
|
||||
#urlbar-container {
|
||||
min-width: 45ch;
|
||||
min-width: calc(44ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 70px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
#urlbar-container {
|
||||
min-width: 40ch;
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 44ch;
|
||||
}
|
||||
|
||||
#identity-icon-labels {
|
||||
max-width: 60px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 500px) {
|
||||
@media (max-width: 600px) {
|
||||
#urlbar-container {
|
||||
min-width: 35ch;
|
||||
min-width: calc(39ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 39ch;
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 400px) {
|
||||
@media (max-width: 500px) {
|
||||
#urlbar-container {
|
||||
min-width: 28ch;
|
||||
min-width: calc(34ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 34ch;
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 40px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 400px) {
|
||||
#urlbar-container {
|
||||
min-width: calc(27ch + 24px + 2 * var(--toolbarbutton-inner-padding));
|
||||
}
|
||||
#nav-bar[downloadsbuttonshown] #urlbar-container {
|
||||
min-width: 27ch;
|
||||
}
|
||||
#identity-icon-labels {
|
||||
max-width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
#identity-icon-country-label {
|
||||
direction: ltr;
|
||||
|
||||
@@ -1321,6 +1321,10 @@ var gBrowserInit = {
|
||||
|
||||
SidebarUI.init();
|
||||
|
||||
// We do this in onload because we want to ensure the button's state
|
||||
// doesn't flicker as the window is being shown.
|
||||
DownloadsButton.init();
|
||||
|
||||
// Certain kinds of automigration rely on this notification to complete
|
||||
// their tasks BEFORE the browser window is shown. SessionStore uses it to
|
||||
// restore tabs into windows AFTER important parts like gMultiProcessBrowser
|
||||
@@ -1847,6 +1851,8 @@ var gBrowserInit = {
|
||||
|
||||
SidebarUI.uninit();
|
||||
|
||||
DownloadsButton.uninit();
|
||||
|
||||
// Now either cancel delayedStartup, or clean up the services initialized from
|
||||
// it.
|
||||
if (this._boundDelayedStartup) {
|
||||
|
||||
@@ -939,7 +939,9 @@
|
||||
ondragenter="DownloadsIndicatorView.onDragOver(event);"
|
||||
label="&downloads.label;"
|
||||
removable="true"
|
||||
overflows="false"
|
||||
cui-areatype="toolbar"
|
||||
hidden="true"
|
||||
tooltip="dynamic-shortcut-tooltip"/>
|
||||
|
||||
<toolbarbutton id="library-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
|
||||
@@ -74,7 +74,7 @@ async function expectFocusOnF6(backward, expectedDocument, expectedElement, onCo
|
||||
}
|
||||
|
||||
is(fm.focusedWindow.document.documentElement.id, expectedDocument, desc + " document matches");
|
||||
is(fm.focusedElement, expectedElement, desc + " element matches");
|
||||
is(fm.focusedElement, expectedElement, desc + " element matches (wanted: " + expectedElement.id + " got: " + fm.focusedElement.id + ")");
|
||||
|
||||
if (onContent) {
|
||||
window.messageManager.removeMessageListener("BrowserTest:FocusChanged", focusChangedListener);
|
||||
@@ -171,8 +171,9 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
// Navigate when the downloads panel is open
|
||||
add_task(async function() {
|
||||
await pushPrefs(["accessibility.tabfocus", 7]);
|
||||
add_task(async function test_download_focus() {
|
||||
await pushPrefs(["accessibility.tabfocus", 7], ["browser.download.autohideButton", false]);
|
||||
await promiseButtonShown("downloads-button");
|
||||
|
||||
let popupShownPromise = BrowserTestUtils.waitForEvent(document, "popupshown", true);
|
||||
EventUtils.synthesizeMouseAtCenter(document.getElementById("downloads-button"), { });
|
||||
@@ -253,3 +254,12 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
// XXXndeakin add tests for browsers inside of panels
|
||||
|
||||
function promiseButtonShown(id) {
|
||||
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
let target = document.getElementById(id);
|
||||
let bounds = dwu.getBoundsWithoutFlushing(target);
|
||||
return bounds.width > 0 && bounds.height > 0;
|
||||
}, `Waiting for button ${id} to have non-0 size`);
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ const DRAG_WORD = "Firefox";
|
||||
add_task(async function checkDragURL() {
|
||||
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
|
||||
// Have to use something other than the URL bar as a source, so picking the
|
||||
// downloads button somewhat arbitrarily:
|
||||
EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
|
||||
// home button somewhat arbitrarily:
|
||||
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
|
||||
[[{type: "text/plain", data: DRAG_URL}]], "copy", window);
|
||||
is(gURLBar.value, TEST_URL, "URL bar value should not have changed");
|
||||
is(gBrowser.selectedBrowser.userTypedValue, null, "Stored URL bar value should not have changed");
|
||||
@@ -19,7 +19,7 @@ add_task(async function checkDragURL() {
|
||||
|
||||
add_task(async function checkDragForbiddenURL() {
|
||||
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
|
||||
EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
|
||||
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
|
||||
[[{type: "text/plain", data: DRAG_FORBIDDEN_URL}]], "copy", window);
|
||||
isnot(gURLBar.value, DRAG_FORBIDDEN_URL, "Shouldn't be allowed to drop forbidden URL on URL bar");
|
||||
});
|
||||
@@ -27,11 +27,11 @@ add_task(async function checkDragForbiddenURL() {
|
||||
|
||||
add_task(async function checkDragText() {
|
||||
await BrowserTestUtils.withNewTab(TEST_URL, function(browser) {
|
||||
EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
|
||||
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
|
||||
[[{type: "text/plain", data: DRAG_TEXT}]], "copy", window);
|
||||
is(gURLBar.value, DRAG_TEXT, "Dragging normal text should replace the URL bar value");
|
||||
|
||||
EventUtils.synthesizeDrop(document.getElementById("downloads-button"), gURLBar,
|
||||
EventUtils.synthesizeDrop(document.getElementById("home-button"), gURLBar,
|
||||
[[{type: "text/plain", data: DRAG_WORD}]], "copy", window);
|
||||
is(gURLBar.value, DRAG_WORD, "Dragging a single word should replace the URL bar value");
|
||||
});
|
||||
|
||||
@@ -40,6 +40,7 @@ const kPrefCustomizationDebug = "browser.uiCustomization.debug";
|
||||
const kPrefDrawInTitlebar = "browser.tabs.drawInTitlebar";
|
||||
const kPrefUIDensity = "browser.uidensity";
|
||||
const kPrefAutoTouchMode = "browser.touchmode.auto";
|
||||
const kPrefAutoHideDownloadsButton = "browser.download.autohideButton";
|
||||
|
||||
const kExpectedWindowURL = "chrome://browser/content/browser.xul";
|
||||
|
||||
@@ -177,7 +178,7 @@ var CustomizableUIInternal = {
|
||||
this.addListener(this);
|
||||
this._defineBuiltInWidgets();
|
||||
this.loadSavedState();
|
||||
this._introduceNewBuiltinWidgets();
|
||||
this._updateForNewVersion();
|
||||
this._markObsoleteBuiltinButtonsSeen();
|
||||
|
||||
this.registerArea(CustomizableUI.AREA_FIXED_OVERFLOW_PANEL, {
|
||||
@@ -262,7 +263,7 @@ var CustomizableUIInternal = {
|
||||
}
|
||||
},
|
||||
|
||||
_introduceNewBuiltinWidgets() {
|
||||
_updateForNewVersion() {
|
||||
// We should still enter even if gSavedState.currentVersion >= kVersion
|
||||
// because the per-widget pref facility is independent of versioning.
|
||||
if (!gSavedState) {
|
||||
@@ -2597,6 +2598,7 @@ var CustomizableUIInternal = {
|
||||
gUIStateBeforeReset.uiDensity = Services.prefs.getIntPref(kPrefUIDensity);
|
||||
gUIStateBeforeReset.autoTouchMode = Services.prefs.getBoolPref(kPrefAutoTouchMode);
|
||||
gUIStateBeforeReset.currentTheme = LightweightThemeManager.currentTheme;
|
||||
gUIStateBeforeReset.autoHideDownloadsButton = Services.prefs.getBoolPref(kPrefAutoHideDownloadsButton);
|
||||
gUIStateBeforeReset.newElementCount = gNewElementCount;
|
||||
} catch (e) { }
|
||||
|
||||
@@ -2606,6 +2608,7 @@ var CustomizableUIInternal = {
|
||||
Services.prefs.clearUserPref(kPrefDrawInTitlebar);
|
||||
Services.prefs.clearUserPref(kPrefUIDensity);
|
||||
Services.prefs.clearUserPref(kPrefAutoTouchMode);
|
||||
Services.prefs.clearUserPref(kPrefAutoHideDownloadsButton);
|
||||
LightweightThemeManager.currentTheme = null;
|
||||
gNewElementCount = 0;
|
||||
log.debug("State reset");
|
||||
@@ -2674,11 +2677,10 @@ var CustomizableUIInternal = {
|
||||
}
|
||||
gUndoResetting = true;
|
||||
|
||||
let uiCustomizationState = gUIStateBeforeReset.uiCustomizationState;
|
||||
let drawInTitlebar = gUIStateBeforeReset.drawInTitlebar;
|
||||
let currentTheme = gUIStateBeforeReset.currentTheme;
|
||||
let uiDensity = gUIStateBeforeReset.uiDensity;
|
||||
let autoTouchMode = gUIStateBeforeReset.autoTouchMode;
|
||||
const {
|
||||
uiCustomizationState, drawInTitlebar, currentTheme, uiDensity,
|
||||
autoTouchMode, autoHideDownloadsButton,
|
||||
} = gUIStateBeforeReset;
|
||||
gNewElementCount = gUIStateBeforeReset.newElementCount;
|
||||
|
||||
// Need to clear the previous state before setting the prefs
|
||||
@@ -2689,6 +2691,7 @@ var CustomizableUIInternal = {
|
||||
Services.prefs.setBoolPref(kPrefDrawInTitlebar, drawInTitlebar);
|
||||
Services.prefs.setIntPref(kPrefUIDensity, uiDensity);
|
||||
Services.prefs.setBoolPref(kPrefAutoTouchMode, autoTouchMode);
|
||||
Services.prefs.setBoolPref(kPrefAutoHideDownloadsButton, autoHideDownloadsButton);
|
||||
LightweightThemeManager.currentTheme = currentTheme;
|
||||
this.loadSavedState();
|
||||
// If the user just customizes toolbar/titlebar visibility, gSavedState will be null
|
||||
|
||||
@@ -19,7 +19,7 @@ function test() {
|
||||
"All future placements should be dealt with by now.");
|
||||
|
||||
let {CustomizableUIInternal, gFuturePlacements, gPalette} = CustomizableUIBSPass;
|
||||
CustomizableUIInternal._introduceNewBuiltinWidgets();
|
||||
CustomizableUIInternal._updateForNewVersion();
|
||||
is(gFuturePlacements.size, 0,
|
||||
"No change to future placements initially.");
|
||||
|
||||
@@ -67,7 +67,7 @@ function test() {
|
||||
}
|
||||
|
||||
// Then call the re-init routine so we re-add the builtin widgets
|
||||
CustomizableUIInternal._introduceNewBuiltinWidgets();
|
||||
CustomizableUIInternal._updateForNewVersion();
|
||||
is(gFuturePlacements.size, 1,
|
||||
"Should have 1 more future placement");
|
||||
let haveNavbarPlacements = gFuturePlacements.has(CustomizableUI.AREA_NAVBAR);
|
||||
@@ -106,7 +106,7 @@ function test() {
|
||||
"PanelUI-contents": ["panic-button", "edit-controls"],
|
||||
},
|
||||
};
|
||||
CustomizableUIInternal._introduceNewBuiltinWidgets();
|
||||
CustomizableUIInternal._updateForNewVersion();
|
||||
let navbarPlacements = CustomizableUIBSPass.gSavedState.placements["nav-bar"];
|
||||
let springs = navbarPlacements.filter(id => id.includes("spring"));
|
||||
is(springs.length, 2, "Should have 2 toolbarsprings in placements now");
|
||||
|
||||
@@ -17,7 +17,7 @@ function test() {
|
||||
CustomizableUIInternal.saveState();
|
||||
CustomizableUIInternal.loadSavedState();
|
||||
|
||||
CustomizableUIInternal._introduceNewBuiltinWidgets();
|
||||
CustomizableUIInternal._updateForNewVersion();
|
||||
is(gFuturePlacements.size, 0,
|
||||
"No change to future placements initially.");
|
||||
|
||||
@@ -44,7 +44,7 @@ function test() {
|
||||
|
||||
let savedPlacements = CustomizableUIBSPass.gSavedState.placements[CustomizableUI.AREA_NAVBAR];
|
||||
// Then call the re-init routine so we re-add the builtin widgets
|
||||
CustomizableUIInternal._introduceNewBuiltinWidgets();
|
||||
CustomizableUIInternal._updateForNewVersion();
|
||||
is(gFuturePlacements.size, 1,
|
||||
"Should have 1 more future placement");
|
||||
let futureNavbarPlacements = gFuturePlacements.get(CustomizableUI.AREA_NAVBAR);
|
||||
|
||||
@@ -16,17 +16,17 @@ add_task(async function() {
|
||||
skippedItem.setAttribute("skipintoolbarset", "true");
|
||||
skippedItem.setAttribute("removable", "true");
|
||||
navbar.customizationTarget.appendChild(skippedItem);
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
let libraryButton = document.getElementById("library-button");
|
||||
await startCustomizing();
|
||||
ok(CustomizableUI.inDefaultState, "Should still be in default state");
|
||||
simulateItemDrag(skippedItem, downloadsButton);
|
||||
simulateItemDrag(skippedItem, libraryButton);
|
||||
ok(CustomizableUI.inDefaultState, "Should still be in default state");
|
||||
let skippedItemWrapper = skippedItem.parentNode;
|
||||
is(skippedItemWrapper.nextSibling && skippedItemWrapper.nextSibling.id,
|
||||
downloadsButton.parentNode.id, "Should be next to downloads button");
|
||||
simulateItemDrag(downloadsButton, skippedItem);
|
||||
let downloadWrapper = downloadsButton.parentNode;
|
||||
is(downloadWrapper.nextSibling && downloadWrapper.nextSibling.id,
|
||||
libraryButton.parentNode.id, "Should be next to library button");
|
||||
simulateItemDrag(libraryButton, skippedItem);
|
||||
let libraryWrapper = libraryButton.parentNode;
|
||||
is(libraryWrapper.nextSibling && libraryWrapper.nextSibling.id,
|
||||
skippedItem.parentNode.id, "Should be next to skipintoolbarset item");
|
||||
ok(CustomizableUI.inDefaultState, "Should still be in default state");
|
||||
});
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
add_task(async function() {
|
||||
await startCustomizing();
|
||||
let devButton = document.getElementById("developer-button");
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
let libraryButton = document.getElementById("library-button");
|
||||
let homeButton = document.getElementById("home-button");
|
||||
let palette = document.getElementById("customization-palette");
|
||||
ok(devButton && downloadsButton && homeButton && palette, "Stuff should exist");
|
||||
simulateItemDrag(devButton, downloadsButton);
|
||||
ok(devButton && libraryButton && homeButton && palette, "Stuff should exist");
|
||||
simulateItemDrag(devButton, libraryButton);
|
||||
simulateItemDrag(homeButton, palette);
|
||||
await gCustomizeMode.reset();
|
||||
ok(CustomizableUI.inDefaultState, "Should be back in default state");
|
||||
|
||||
@@ -10,11 +10,11 @@ const kTestToolbarId = "test-empty-drag";
|
||||
add_task(async function() {
|
||||
await createToolbarWithPlacements(kTestToolbarId, []);
|
||||
await startCustomizing();
|
||||
let downloadButton = document.getElementById("downloads-button");
|
||||
let libraryButton = document.getElementById("library-button");
|
||||
let customToolbar = document.getElementById(kTestToolbarId);
|
||||
simulateItemDrag(downloadButton, customToolbar);
|
||||
assertAreaPlacements(kTestToolbarId, ["downloads-button"]);
|
||||
ok(downloadButton.parentNode && downloadButton.parentNode.parentNode == customToolbar,
|
||||
simulateItemDrag(libraryButton, customToolbar);
|
||||
assertAreaPlacements(kTestToolbarId, ["library-button"]);
|
||||
ok(libraryButton.parentNode && libraryButton.parentNode.parentNode == customToolbar,
|
||||
"Button should really be in toolbar");
|
||||
await endCustomizing();
|
||||
removeCustomToolbars();
|
||||
|
||||
@@ -44,12 +44,12 @@ add_task(async function() {
|
||||
// Drag an item and drop it onto the nav-bar customization target, but
|
||||
// not over a particular item.
|
||||
await startCustomizing();
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
simulateItemDrag(downloadsButton, navbar.customizationTarget);
|
||||
let homeButton = document.getElementById("home-button");
|
||||
simulateItemDrag(homeButton, navbar.customizationTarget);
|
||||
|
||||
await endCustomizing();
|
||||
|
||||
is(downloadsButton.previousSibling.id, lastVisible.id,
|
||||
is(homeButton.previousSibling.id, lastVisible.id,
|
||||
"The downloads button should be placed after the last visible item.");
|
||||
|
||||
await resetCustomization();
|
||||
|
||||
@@ -3,12 +3,14 @@
|
||||
const kOverflowPanel = document.getElementById("widget-overflow");
|
||||
|
||||
var gOriginalWidth;
|
||||
registerCleanupFunction(async function() {
|
||||
async function stopOverflowing() {
|
||||
kOverflowPanel.removeAttribute("animate");
|
||||
window.resizeTo(gOriginalWidth, window.outerHeight);
|
||||
await waitForCondition(() => !document.getElementById("nav-bar").hasAttribute("overflowing"));
|
||||
CustomizableUI.reset();
|
||||
});
|
||||
}
|
||||
|
||||
registerCleanupFunction(stopOverflowing);
|
||||
|
||||
/**
|
||||
* This checks that subview-compatible items show up as subviews rather than
|
||||
@@ -42,6 +44,7 @@ add_task(async function check_developer_subview_in_overflow() {
|
||||
is(developerView.closest("panel"), expectedPanel, "Should be inside the panel");
|
||||
expectedPanel.hidePopup();
|
||||
await Promise.resolve(); // wait for popup to hide fully.
|
||||
await stopOverflowing();
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -51,14 +54,15 @@ add_task(async function check_developer_subview_in_overflow() {
|
||||
* simplify some of the subview anchoring code.
|
||||
*/
|
||||
add_task(async function check_downloads_panel_in_overflow() {
|
||||
let navbar = document.getElementById(CustomizableUI.AREA_NAVBAR);
|
||||
ok(navbar.hasAttribute("overflowing"), "Should still be overflowing");
|
||||
let button = document.getElementById("downloads-button");
|
||||
gCustomizeMode.addToPanel(button);
|
||||
await waitForOverflowButtonShown();
|
||||
|
||||
let chevron = document.getElementById("nav-bar-overflow-button");
|
||||
let shownPanelPromise = promisePanelElementShown(window, kOverflowPanel);
|
||||
chevron.click();
|
||||
await shownPanelPromise;
|
||||
|
||||
let button = document.getElementById("downloads-button");
|
||||
button.click();
|
||||
await waitForCondition(() => {
|
||||
let panel = document.getElementById("downloadsPanel");
|
||||
|
||||
@@ -223,6 +223,9 @@ var DownloadsPanel = {
|
||||
return;
|
||||
}
|
||||
|
||||
// As a belt-and-suspenders check, ensure the button is not hidden.
|
||||
DownloadsButton.unhide();
|
||||
|
||||
this.initialize(() => {
|
||||
// Delay displaying the panel because this function will sometimes be
|
||||
// called while another window is closing (like the window for selecting
|
||||
|
||||
@@ -54,6 +54,11 @@ const DownloadsButton = {
|
||||
return document.getElementById("downloads-button");
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates whether toolbar customization is in progress.
|
||||
*/
|
||||
_customizing: false,
|
||||
|
||||
/**
|
||||
* This function is called asynchronously just after window initialization.
|
||||
*
|
||||
@@ -64,34 +69,6 @@ const DownloadsButton = {
|
||||
DownloadsIndicatorView.ensureInitialized();
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates whether toolbar customization is in progress.
|
||||
*/
|
||||
_customizing: false,
|
||||
|
||||
/**
|
||||
* This function is called when toolbar customization starts.
|
||||
*
|
||||
* During customization, we never show the actual download progress indication
|
||||
* or the event notifications, but we show a neutral placeholder. The neutral
|
||||
* placeholder is an ordinary button defined in the browser window that can be
|
||||
* moved freely between the toolbars and the customization palette.
|
||||
*/
|
||||
customizeStart() {
|
||||
// Prevent the indicator from being displayed as a temporary anchor
|
||||
// during customization, even if requested using the getAnchor method.
|
||||
this._customizing = true;
|
||||
this._anchorRequested = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* This function is called when toolbar customization ends.
|
||||
*/
|
||||
customizeDone() {
|
||||
this._customizing = false;
|
||||
DownloadsIndicatorView.afterCustomize();
|
||||
},
|
||||
|
||||
/**
|
||||
* Determines the position where the indicator should appear, and moves its
|
||||
* associated element to the new position.
|
||||
@@ -108,35 +85,16 @@ const DownloadsButton = {
|
||||
|
||||
indicator.open = this._anchorRequested;
|
||||
|
||||
let widget = CustomizableUI.getWidget("downloads-button")
|
||||
.forWindow(window);
|
||||
let widget = CustomizableUI.getWidget("downloads-button");
|
||||
// Determine if the indicator is located on an invisible toolbar.
|
||||
if (!isElementVisible(indicator.parentNode) && !widget.overflowed) {
|
||||
if (!isElementVisible(indicator.parentNode) &&
|
||||
widget.areaType == CustomizableUI.TYPE_TOOLBAR) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DownloadsIndicatorView.indicatorAnchor;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether the indicator is, or will soon be visible in the browser
|
||||
* window.
|
||||
*
|
||||
* @param aCallback
|
||||
* Called once the indicator overlay has loaded. Gets a boolean
|
||||
* argument representing the indicator visibility.
|
||||
*/
|
||||
checkIsVisible(aCallback) {
|
||||
DownloadsOverlayLoader.ensureOverlayLoaded(this.kIndicatorOverlay, () => {
|
||||
if (!this._placeholder) {
|
||||
aCallback(false);
|
||||
} else {
|
||||
let element = DownloadsIndicatorView.indicator || this._placeholder;
|
||||
aCallback(isElementVisible(element.parentNode));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Indicates whether we should try and show the indicator temporarily as an
|
||||
* anchor for the panel, even if the indicator would be hidden by default.
|
||||
@@ -172,6 +130,91 @@ const DownloadsButton = {
|
||||
this._getAnchorInternal();
|
||||
},
|
||||
|
||||
unhide() {
|
||||
let button = this._placeholder;
|
||||
if (button && button.hasAttribute("hidden")) {
|
||||
button.removeAttribute("hidden");
|
||||
if (this._navBar.contains(button)) {
|
||||
this._navBar.setAttribute("downloadsbuttonshown", "true");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hide() {
|
||||
let button = this._placeholder;
|
||||
if (this.autoHideDownloadsButton && button && button.closest("toolbar")) {
|
||||
DownloadsPanel.hidePanel();
|
||||
button.setAttribute("hidden", "true");
|
||||
this._navBar.removeAttribute("downloadsbuttonshown");
|
||||
}
|
||||
},
|
||||
|
||||
startAutoHide() {
|
||||
if (DownloadsIndicatorView.hasDownloads) {
|
||||
this.unhide();
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
checkForAutoHide() {
|
||||
let button = this._placeholder;
|
||||
if (!this._customizing && this.autoHideDownloadsButton &&
|
||||
button && button.closest("toolbar")) {
|
||||
this.startAutoHide();
|
||||
} else {
|
||||
this.unhide();
|
||||
}
|
||||
},
|
||||
|
||||
// Callback from CustomizableUI when nodes get moved around.
|
||||
// We use this to track whether our node has moved somewhere
|
||||
// where we should (not) autohide it.
|
||||
onWidgetAfterDOMChange(node) {
|
||||
if (node == this._placeholder) {
|
||||
this.checkForAutoHide();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* This function is called when toolbar customization starts.
|
||||
*
|
||||
* During customization, we never show the actual download progress indication
|
||||
* or the event notifications, but we show a neutral placeholder. The neutral
|
||||
* placeholder is an ordinary button defined in the browser window that can be
|
||||
* moved freely between the toolbars and the customization palette.
|
||||
*/
|
||||
onCustomizeStart(win) {
|
||||
if (win == window) {
|
||||
// Prevent the indicator from being displayed as a temporary anchor
|
||||
// during customization, even if requested using the getAnchor method.
|
||||
this._customizing = true;
|
||||
this._anchorRequested = false;
|
||||
this.unhide();
|
||||
}
|
||||
},
|
||||
|
||||
onCustomizeEnd(win) {
|
||||
if (win == window) {
|
||||
this._customizing = false;
|
||||
this.checkForAutoHide();
|
||||
DownloadsIndicatorView.afterCustomize();
|
||||
}
|
||||
},
|
||||
|
||||
init() {
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this, "autoHideDownloadsButton", "browser.download.autohideButton",
|
||||
true, this.checkForAutoHide.bind(this));
|
||||
|
||||
CustomizableUI.addListener(this);
|
||||
this.checkForAutoHide();
|
||||
},
|
||||
|
||||
uninit() {
|
||||
CustomizableUI.removeListener(this);
|
||||
},
|
||||
|
||||
get _tabsToolbar() {
|
||||
delete this._tabsToolbar;
|
||||
return this._tabsToolbar = document.getElementById("TabsToolbar");
|
||||
@@ -342,7 +385,7 @@ const DownloadsIndicatorView = {
|
||||
let anchor = DownloadsButton._placeholder;
|
||||
let widgetGroup = CustomizableUI.getWidget("downloads-button");
|
||||
let widget = widgetGroup.forWindow(window);
|
||||
if (widget.overflowed || widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
if (anchor && this._isAncestorPanelOpen(anchor)) {
|
||||
// If the containing panel is open, don't do anything, because the
|
||||
// notification would appear under the open panel. See
|
||||
@@ -423,8 +466,12 @@ const DownloadsIndicatorView = {
|
||||
this._hasDownloads = aValue;
|
||||
|
||||
// If there is at least one download, ensure that the view elements are
|
||||
// operational
|
||||
if (aValue) {
|
||||
DownloadsButton.unhide();
|
||||
this._ensureOperational();
|
||||
} else {
|
||||
DownloadsButton.checkForAutoHide();
|
||||
}
|
||||
}
|
||||
return aValue;
|
||||
@@ -508,14 +555,7 @@ const DownloadsIndicatorView = {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the downloads button is in the menu panel, open the Library
|
||||
let widgetGroup = CustomizableUI.getWidget("downloads-button");
|
||||
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
DownloadsPanel.showDownloadsHistory();
|
||||
} else {
|
||||
DownloadsPanel.showPanel();
|
||||
}
|
||||
|
||||
DownloadsPanel.showPanel();
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
@@ -567,10 +607,9 @@ const DownloadsIndicatorView = {
|
||||
},
|
||||
|
||||
get indicatorAnchor() {
|
||||
let widget = CustomizableUI.getWidget("downloads-button")
|
||||
.forWindow(window);
|
||||
if (widget.overflowed) {
|
||||
return widget.anchor;
|
||||
let widgetGroup = CustomizableUI.getWidget("downloads-button");
|
||||
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
return widgetGroup.forWindow(window).anchor;
|
||||
}
|
||||
return document.getElementById("downloads-indicator-anchor");
|
||||
},
|
||||
|
||||
@@ -13,3 +13,4 @@ skip-if = os == "linux" # Bug 952422
|
||||
[browser_downloads_panel_block.js]
|
||||
skip-if = true # Bug 1352792
|
||||
[browser_downloads_panel_height.js]
|
||||
[browser_downloads_autohide.js]
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const kDownloadAutoHidePref = "browser.download.autohideButton";
|
||||
|
||||
registerCleanupFunction(async function() {
|
||||
Services.prefs.clearUserPref(kDownloadAutoHidePref);
|
||||
if (document.documentElement.hasAttribute("customizing")) {
|
||||
await gCustomizeMode.reset();
|
||||
await promiseCustomizeEnd();
|
||||
} else {
|
||||
CustomizableUI.reset();
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function checkStateDuringPrefFlips() {
|
||||
ok(Services.prefs.getBoolPref(kDownloadAutoHidePref),
|
||||
"Should be autohiding the button by default");
|
||||
ok(!DownloadsIndicatorView.hasDownloads,
|
||||
"Should be no downloads when starting the test");
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden in the toolbar");
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button shouldn't be hidden in the panel");
|
||||
gCustomizeMode.addToToolbar(downloadsButton);
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden again in the toolbar");
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, false);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button shouldn't be hidden with autohide turned off");
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button shouldn't be hidden with autohide turned off " +
|
||||
"after moving it to the panel");
|
||||
gCustomizeMode.addToToolbar(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button shouldn't be hidden with autohide turned off " +
|
||||
"after moving it back to the toolbar");
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, true);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still not be hidden with autohide turned back on " +
|
||||
"because it's in the panel");
|
||||
gCustomizeMode.addToToolbar(downloadsButton);
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden again in the toolbar");
|
||||
gCustomizeMode.removeFromArea(downloadsButton);
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, false);
|
||||
// Can't use gCustomizeMode.addToToolbar here because it doesn't work for
|
||||
// palette items if the window isn't in customize mode:
|
||||
CustomizableUI.addWidgetToArea(downloadsButton.id, CustomizableUI.AREA_NAVBAR);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be unhidden again in the toolbar " +
|
||||
"even if the pref was flipped while the button was in the palette");
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, true);
|
||||
});
|
||||
|
||||
add_task(async function checkStateInCustomizeMode() {
|
||||
ok(Services.prefs.getBoolPref("browser.download.autohideButton"),
|
||||
"Should be autohiding the button");
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
await promiseCustomizeStart();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode.");
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode when moved to the panel");
|
||||
gCustomizeMode.addToToolbar(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode when moved back to the toolbar");
|
||||
gCustomizeMode.removeFromArea(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode when in the palette");
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, false);
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, true);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode " +
|
||||
"even when flipping the autohide pref");
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
await promiseCustomizeEnd();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown after customize mode when moved to the panel");
|
||||
await promiseCustomizeStart();
|
||||
gCustomizeMode.addToToolbar(downloadsButton);
|
||||
await promiseCustomizeEnd();
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden if it's in the toolbar after customize mode.");
|
||||
await promiseCustomizeStart();
|
||||
await gCustomizeMode.reset();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the toolbar in customize mode after a reset.");
|
||||
await gCustomizeMode.undoReset();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the toolbar in customize mode " +
|
||||
"when undoing the reset.");
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
await gCustomizeMode.reset();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the toolbar in customize mode " +
|
||||
"after a reset moved it.");
|
||||
await gCustomizeMode.undoReset();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the panel in customize mode " +
|
||||
"when undoing the reset.");
|
||||
await gCustomizeMode.reset();
|
||||
await promiseCustomizeEnd();
|
||||
});
|
||||
|
||||
add_task(async function checkStateInCustomizeModeMultipleWindows() {
|
||||
ok(Services.prefs.getBoolPref("browser.download.autohideButton"),
|
||||
"Should be autohiding the button");
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
await promiseCustomizeStart();
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode.");
|
||||
let otherWin = await BrowserTestUtils.openNewBrowserWindow();
|
||||
let otherDownloadsButton = otherWin.document.getElementById("downloads-button");
|
||||
ok(otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden in the other window.");
|
||||
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be shown in customize mode.");
|
||||
ok(!otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the other window too because it's in a panel.");
|
||||
|
||||
gCustomizeMode.addToToolbar(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be shown in customize mode.");
|
||||
ok(otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden again in the other window.");
|
||||
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, false);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode");
|
||||
ok(!otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the other window with the pref flipped");
|
||||
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, true);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in customize mode " +
|
||||
"even when flipping the autohide pref");
|
||||
ok(otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden in the other window with the pref flipped again");
|
||||
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be shown in customize mode.");
|
||||
ok(!otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be shown in the other window too because it's in a panel.");
|
||||
|
||||
gCustomizeMode.removeFromArea(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be shown in customize mode.");
|
||||
// Don't need to assert in the other window - button is gone there.
|
||||
|
||||
await gCustomizeMode.reset();
|
||||
ok(Services.prefs.getBoolPref(kDownloadAutoHidePref),
|
||||
"Autohide pref reset by reset()");
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be shown in customize mode.");
|
||||
ok(otherDownloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden in the other window.");
|
||||
ok(otherDownloadsButton.closest("#nav-bar"),
|
||||
"Button should be back in the nav bar in the other window.");
|
||||
|
||||
await promiseCustomizeEnd();
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden again outside of customize mode");
|
||||
await BrowserTestUtils.closeWindow(otherWin);
|
||||
});
|
||||
|
||||
add_task(async function checkStateForDownloads() {
|
||||
ok(Services.prefs.getBoolPref("browser.download.autohideButton"),
|
||||
"Should be autohiding the button");
|
||||
let downloadsButton = document.getElementById("downloads-button");
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden when there are no downloads.");
|
||||
|
||||
await task_addDownloads([
|
||||
{ state: DownloadsCommon.DOWNLOAD_DOWNLOADING },
|
||||
]);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be unhidden when there are downloads.");
|
||||
let publicList = await Downloads.getList(Downloads.PUBLIC);
|
||||
let downloads = await publicList.getAll();
|
||||
for (let download of downloads) {
|
||||
publicList.remove(download);
|
||||
}
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden when the download is removed");
|
||||
await task_addDownloads([
|
||||
{ state: DownloadsCommon.DOWNLOAD_DOWNLOADING },
|
||||
]);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be unhidden when there are downloads.");
|
||||
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, false);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be unhidden.");
|
||||
|
||||
downloads = await publicList.getAll();
|
||||
for (let download of downloads) {
|
||||
publicList.remove(download);
|
||||
}
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still be unhidden because the pref was flipped.");
|
||||
Services.prefs.setBoolPref(kDownloadAutoHidePref, true);
|
||||
ok(downloadsButton.hasAttribute("hidden"),
|
||||
"Button should be hidden now that the pref flipped back " +
|
||||
"because there were already no downloads.");
|
||||
|
||||
gCustomizeMode.addToPanel(downloadsButton);
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should not be hidden in the panel.");
|
||||
|
||||
await task_addDownloads([
|
||||
{ state: DownloadsCommon.DOWNLOAD_DOWNLOADING },
|
||||
]);
|
||||
|
||||
downloads = await publicList.getAll();
|
||||
for (let download of downloads) {
|
||||
publicList.remove(download);
|
||||
}
|
||||
|
||||
ok(!downloadsButton.hasAttribute("hidden"),
|
||||
"Button should still not be hidden in the panel " +
|
||||
"when downloads count reaches 0 after being non-0.");
|
||||
});
|
||||
|
||||
function promiseCustomizeStart(aWindow = window) {
|
||||
return new Promise(resolve => {
|
||||
aWindow.gNavToolbox.addEventListener("customizationready", resolve,
|
||||
{once: true});
|
||||
aWindow.gCustomizeMode.enter();
|
||||
});
|
||||
}
|
||||
|
||||
function promiseCustomizeEnd(aWindow = window) {
|
||||
return new Promise(resolve => {
|
||||
aWindow.gNavToolbox.addEventListener("aftercustomization", resolve,
|
||||
{once: true});
|
||||
aWindow.gCustomizeMode.exit();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
* updated correctly if downloads are removed while the panel is hidden.
|
||||
*/
|
||||
add_task(async function test_height_reduced_after_removal() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["browser.download.autohideButton", false]]});
|
||||
await promiseButtonShown("downloads-button");
|
||||
await task_addDownloads([
|
||||
{ state: DownloadsCommon.DOWNLOAD_FINISHED },
|
||||
]);
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
* not open the panel automatically.
|
||||
*/
|
||||
add_task(async function test_first_download_panel() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["browser.download.autohideButton", false]]});
|
||||
await promiseButtonShown("downloads-button");
|
||||
// Clear the download panel has shown preference first as this test is used to
|
||||
// verify this preference's behaviour.
|
||||
let oldPrefValue = Services.prefs.getBoolPref("browser.download.panel.shown");
|
||||
@@ -32,6 +34,7 @@ add_task(async function test_first_download_panel() {
|
||||
// time a download is started.
|
||||
DownloadsCommon.getData(window).panelHasShownBefore = false;
|
||||
|
||||
info("waiting for panel open");
|
||||
let promise = promisePanelOpened();
|
||||
DownloadsCommon.getData(window)._notifyDownloadEvent("start");
|
||||
await promise;
|
||||
|
||||
@@ -12,8 +12,10 @@ registerCleanupFunction(async function() {
|
||||
});
|
||||
|
||||
add_task(async function test_indicatorDrop() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["browser.download.autohideButton", false]]});
|
||||
let downloadButton = document.getElementById("downloads-button");
|
||||
ok(downloadButton, "download button present");
|
||||
await promiseButtonShown(downloadButton.id);
|
||||
|
||||
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
|
||||
getService(Ci.mozIJSSubScriptLoader);
|
||||
|
||||
@@ -15,30 +15,21 @@ registerCleanupFunction(async function() {
|
||||
* panel that the downloads panel anchors to the chevron.
|
||||
*/
|
||||
add_task(async function test_overflow_anchor() {
|
||||
await SpecialPowers.pushPrefEnv({set: [["browser.download.autohideButton", false]]});
|
||||
// Ensure that state is reset in case previous tests didn't finish.
|
||||
await task_resetState();
|
||||
|
||||
// Record the original width of the window so we can put it back when
|
||||
// this test finishes.
|
||||
let oldWidth = window.outerWidth;
|
||||
|
||||
// The downloads button should not be overflowed to begin with.
|
||||
let button = CustomizableUI.getWidget("downloads-button")
|
||||
.forWindow(window);
|
||||
ok(!button.overflowed, "Downloads button should not be overflowed.");
|
||||
is(button.node.getAttribute("cui-areatype"), "toolbar", "Button should know it's in the toolbar");
|
||||
|
||||
// Hack - we lock the size of the default flex-y items in the nav-bar, namely,
|
||||
// the URL input. That way we can resize the window without worrying about it
|
||||
// flexing.
|
||||
const kFlexyItems = ["urlbar-container"];
|
||||
registerCleanupFunction(() => unlockWidth(kFlexyItems));
|
||||
lockWidth(kFlexyItems);
|
||||
|
||||
window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
|
||||
await waitForOverflowed(button, true);
|
||||
gCustomizeMode.addToPanel(button.node);
|
||||
|
||||
let promise = promisePanelOpened();
|
||||
EventUtils.sendMouseEvent({ type: "mousedown", button: 0 }, button.node);
|
||||
info("waiting for panel to open");
|
||||
await promise;
|
||||
|
||||
let panel = DownloadsPanel.panel;
|
||||
@@ -47,14 +38,7 @@ add_task(async function test_overflow_anchor() {
|
||||
|
||||
DownloadsPanel.hidePanel();
|
||||
|
||||
// Unlock the widths on the flex-y items.
|
||||
unlockWidth(kFlexyItems);
|
||||
|
||||
// Put the window back to its original dimensions.
|
||||
window.resizeTo(oldWidth, window.outerHeight);
|
||||
|
||||
// The downloads button should eventually be un-overflowed.
|
||||
await waitForOverflowed(button, false);
|
||||
gCustomizeMode.addToToolbar(button.node);
|
||||
|
||||
// Now try opening the panel again.
|
||||
promise = promisePanelOpened();
|
||||
@@ -66,50 +50,3 @@ add_task(async function test_overflow_anchor() {
|
||||
DownloadsPanel.hidePanel();
|
||||
});
|
||||
|
||||
/**
|
||||
* For some node IDs, finds the nodes and sets their min-width's to their
|
||||
* current width, preventing them from flex-shrinking.
|
||||
*
|
||||
* @param aItemIDs an array of item IDs to set min-width on.
|
||||
*/
|
||||
function lockWidth(aItemIDs) {
|
||||
for (let itemID of aItemIDs) {
|
||||
let item = document.getElementById(itemID);
|
||||
let curWidth = item.getBoundingClientRect().width + "px";
|
||||
item.style.minWidth = curWidth;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the min-width's set on a set of IDs by lockWidth.
|
||||
*
|
||||
* @param aItemIDs an array of ItemIDs to remove min-width on.
|
||||
*/
|
||||
function unlockWidth(aItemIDs) {
|
||||
for (let itemID of aItemIDs) {
|
||||
let item = document.getElementById(itemID);
|
||||
item.style.minWidth = "";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a node to enter or exit the overflowed state.
|
||||
*
|
||||
* @param aItem the node to wait for.
|
||||
* @param aIsOverflowed if we're waiting for the item to be overflowed.
|
||||
*/
|
||||
function waitForOverflowed(aItem, aIsOverflowed) {
|
||||
if (aItem.overflowed == aIsOverflowed) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return new Promise(resolve => {
|
||||
let observer = new MutationObserver(function(aMutations) {
|
||||
if (aItem.overflowed == aIsOverflowed) {
|
||||
observer.disconnect();
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
observer.observe(aItem.node, {attributes: true});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -198,3 +198,15 @@ function promiseAlertDialogOpen(buttonAction) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a given button to become visible.
|
||||
*/
|
||||
function promiseButtonShown(id) {
|
||||
let dwu = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
|
||||
return BrowserTestUtils.waitForCondition(() => {
|
||||
let target = document.getElementById(id);
|
||||
let bounds = dwu.getBoundsWithoutFlushing(target);
|
||||
return bounds.width > 0 && bounds.height > 0;
|
||||
}, `Waiting for button ${id} to have non-0 size`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user