diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index 3f64ffa422e5..5235e23283fc 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -269,7 +269,8 @@ nsContextMenu.prototype = { // Use "Bookmark This Link" if on a link. this.showItem("context-bookmarkpage", !(this.isContentSelected || this.onTextInput || this.onLink || - this.onImage || this.onVideo || this.onAudio || this.onSocial)); + this.onImage || this.onVideo || this.onAudio || this.onSocial || + this.onCanvas)); this.showItem("context-bookmarklink", (this.onLink && !this.onMailtoLink && !this.onSocial) || this.onPlainTextLink); this.showItem("context-keywordfield", diff --git a/browser/base/content/test/general/browser_save_video.js b/browser/base/content/test/general/browser_save_video.js index 2f1e20de0b9b..6361ec468ba1 100644 --- a/browser/base/content/test/general/browser_save_video.js +++ b/browser/base/content/test/general/browser_save_video.js @@ -26,11 +26,13 @@ function test() { EventUtils.synthesizeMouseAtCenter(video1, { type: "contextmenu", button: 2 }, gBrowser.contentWindow); + info("context menu click on video1"); }); }); function contextMenuOpened(event) { event.currentTarget.removeEventListener("popupshown", contextMenuOpened); + info("context menu opened on video1"); // Create the folder the video will be saved into. var destDir = createTemporarySaveDirectory(); @@ -56,6 +58,7 @@ function test() { // Select "Save Video As" option from context menu var saveVideoCommand = document.getElementById("context-savevideo"); saveVideoCommand.doCommand(); + info("context-savevideo command executed"); event.target.hidePopup(); } diff --git a/browser/base/content/test/general/contextmenu_common.js b/browser/base/content/test/general/contextmenu_common.js index 20ad58b1db53..4bb881355641 100644 --- a/browser/base/content/test/general/contextmenu_common.js +++ b/browser/base/content/test/general/contextmenu_common.js @@ -96,10 +96,23 @@ function getVisibleMenuItems(aMenu, aData) { } items.push(item.id); items.push(!item.disabled); - // Add a dummy item to that the indexes in checkMenu are the same + // Add a dummy item so that the indexes in checkMenu are the same // for expectedItems and actualItems. items.push([]); items.push(null); + } else if (item.nodeName == "menugroup") { + ok(item.id, "child menugroup #" + i + " has an ID"); + items.push(item.id); + items.push(!item.disabled); + var menugroupChildren = []; + for (var child of item.children) { + if (child.hidden) + continue; + + menugroupChildren.push([child.id, !child.disabled]); + } + items.push(menugroupChildren); + items.push(null); } else { ok(false, "child #" + i + " of menu ID " + aMenu.id + " has an unknown type (" + item.nodeName + ")"); @@ -114,6 +127,43 @@ function checkContextMenu(expectedItems) { checkMenu(contextMenu, expectedItems, data); } +function checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, index) { + is(actualItem, expectedItem, + "checking item #" + index/2 + " (" + expectedItem + ") name"); + + if (typeof expectedEnabled == "object" && expectedEnabled != null || + typeof actualEnabled == "object" && actualEnabled != null) { + + ok(!(actualEnabled == null), "actualEnabled is not null"); + ok(!(expectedEnabled == null), "expectedEnabled is not null"); + is(typeof actualEnabled, typeof expectedEnabled, "checking types"); + + if (typeof actualEnabled != typeof expectedEnabled || + actualEnabled == null || expectedEnabled == null) + return; + + is(actualEnabled.type, expectedEnabled.type, + "checking item #" + index/2 + " (" + expectedItem + ") type attr value"); + var icon = actualEnabled.icon; + if (icon) { + var tmp = ""; + var j = icon.length - 1; + while (j && icon[j] != "/") { + tmp = icon[j--] + tmp; + } + icon = tmp; + } + is(icon, expectedEnabled.icon, + "checking item #" + index/2 + " (" + expectedItem + ") icon attr value"); + is(actualEnabled.checked, expectedEnabled.checked, + "checking item #" + index/2 + " (" + expectedItem + ") has checked attr"); + is(actualEnabled.disabled, expectedEnabled.disabled, + "checking item #" + index/2 + " (" + expectedItem + ") has disabled attr"); + } else if (expectedEnabled != null) + is(actualEnabled, expectedEnabled, + "checking item #" + index/2 + " (" + expectedItem + ") enabled state"); +} + /* * checkMenu - checks to see if the specified contains the * expected items and state. @@ -136,50 +186,26 @@ function checkMenu(menu, expectedItems, data) { var expectedItem = expectedItems[i]; var expectedEnabled = expectedItems[i + 1]; if (expectedItem instanceof Array) { - ok(true, "Checking submenu..."); - var menuID = expectedItems[i - 2]; // The last item was the menu ID. - var submenu = menu.getElementsByAttribute("id", menuID)[0]; - ok(submenu, "got a submenu element of id='" + menuID + "'"); - if (submenu) { - is(submenu.nodeName, "menu", "submenu element of id='" + menuID + + ok(true, "Checking submenu/menugroup..."); + var previousId = expectedItems[i - 2]; // The last item was the menu ID. + var previousItem = menu.getElementsByAttribute("id", previousId)[0]; + ok(previousItem, (previousItem ? previousItem.nodeName : "item") + " with previous id (" + previousId + ") found"); + if (previousItem && previousItem.nodeName == "menu") { + ok(previousItem, "got a submenu element of id='" + previousId + "'"); + is(previousItem.nodeName, "menu", "submenu element of id='" + previousId + "' has expected nodeName"); - checkMenu(submenu.menupopup, expectedItem, data); + checkMenu(previousItem.menupopup, expectedItem, data, i); + } else if (previousItem && previousItem.nodeName == "menugroup") { + ok(expectedItem.length, "menugroup must not be empty"); + for (var j = 0; j < expectedItem.length / 2; j++) { + checkMenuItem(actualItems[i][j][0], actualItems[i][j][1], expectedItem[j*2], expectedItem[j*2+1], i+j*2); + } + i += j; + } else { + ok(false, "previous item is not a menu or menugroup"); } } else { - is(actualItem, expectedItem, - "checking item #" + i/2 + " (" + expectedItem + ") name"); - - if (typeof expectedEnabled == "object" && expectedEnabled != null || - typeof actualEnabled == "object" && actualEnabled != null) { - - ok(!(actualEnabled == null), "actualEnabled is not null"); - ok(!(expectedEnabled == null), "expectedEnabled is not null"); - is(typeof actualEnabled, typeof expectedEnabled, "checking types"); - - if (typeof actualEnabled != typeof expectedEnabled || - actualEnabled == null || expectedEnabled == null) - continue; - - is(actualEnabled.type, expectedEnabled.type, - "checking item #" + i/2 + " (" + expectedItem + ") type attr value"); - var icon = actualEnabled.icon; - if (icon) { - var tmp = ""; - var j = icon.length - 1; - while (j && icon[j] != "/") { - tmp = icon[j--] + tmp; - } - icon = tmp; - } - is(icon, expectedEnabled.icon, - "checking item #" + i/2 + " (" + expectedItem + ") icon attr value"); - is(actualEnabled.checked, expectedEnabled.checked, - "checking item #" + i/2 + " (" + expectedItem + ") has checked attr"); - is(actualEnabled.disabled, expectedEnabled.disabled, - "checking item #" + i/2 + " (" + expectedItem + ") has disabled attr"); - } else if (expectedEnabled != null) - is(actualEnabled, expectedEnabled, - "checking item #" + i/2 + " (" + expectedItem + ") enabled state"); + checkMenuItem(actualItem, actualEnabled, expectedItem, expectedEnabled, i); } } // Could find unexpected extra items at the end... diff --git a/browser/base/content/test/general/test_contextmenu.html b/browser/base/content/test/general/test_contextmenu.html index 09eb747de606..1a9f1d623701 100644 --- a/browser/base/content/test/general/test_contextmenu.html +++ b/browser/base/content/test/general/test_contextmenu.html @@ -91,11 +91,12 @@ function runTest(testNum) { case 2: // Context menu for plain text - plainTextItems = ["context-back", false, - "context-forward", false, - "context-reload", true, + plainTextItems = ["context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, @@ -163,7 +164,6 @@ function runTest(testNum) { // Context menu for a canvas checkContextMenu(["context-viewimage", true, "context-saveimage", true, - "context-bookmarkpage", true, "context-selectall", true ].concat(inspectItems)); closeContextMenu(); @@ -264,11 +264,12 @@ function runTest(testNum) { case 11: // Context menu for an iframe - checkContextMenu(["context-back", false, - "context-forward", false, - "context-reload", true, + checkContextMenu(["context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, @@ -468,11 +469,12 @@ function runTest(testNum) { "---", null, "+Checkbox", {type: "checkbox", icon: "", checked: false, disabled: false}], null, "---", null, - "context-back", false, - "context-forward", false, - "context-reload", true, + "context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, @@ -501,11 +503,12 @@ function runTest(testNum) { // Context menu for DOM Fullscreen mode (NOTE: this is *NOT* on an img) checkContextMenu(["context-leave-dom-fullscreen", true, "---", null, - "context-back", false, - "context-forward", false, - "context-reload", true, + "context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, @@ -529,11 +532,12 @@ function runTest(testNum) { case 21: // Context menu for element with assigned content context menu // The shift key should bypass content context menu processing - checkContextMenu(["context-back", false, - "context-forward", false, - "context-reload", true, + checkContextMenu(["context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, @@ -693,11 +697,12 @@ function runTest(testNum) { checkContextMenu(["context-ctp-play", true, "context-ctp-hide", true, "---", null, - "context-back", false, - "context-forward", false, - "context-reload", true, + "context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, @@ -730,11 +735,12 @@ function runTest(testNum) { case 29: // Context menu for an iframe with srcdoc attribute set - checkContextMenu(["context-back", false, - "context-forward", false, - "context-reload", true, + checkContextMenu(["context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, diff --git a/browser/base/content/test/general/test_contextmenu_input.html b/browser/base/content/test/general/test_contextmenu_input.html index a0b041e15ade..e0c59f521e68 100644 --- a/browser/base/content/test/general/test_contextmenu_input.html +++ b/browser/base/content/test/general/test_contextmenu_input.html @@ -189,11 +189,12 @@ function runTest(testNum) { case 13: // type='number' case 14: // type='color' case 15: // type='range' - checkContextMenu(["context-back", false, - "context-forward", false, - "context-reload", true, + checkContextMenu(["context-navigation", null, + ["context-back", false, + "context-forward", false, + "context-reload", true, + "context-bookmarkpage", true], null, "---", null, - "context-bookmarkpage", true, "context-savepage", true, "---", null, "context-viewbgimage", false, diff --git a/browser/base/content/test/plugins/browser_CTP_context_menu.js b/browser/base/content/test/plugins/browser_CTP_context_menu.js index bd18b9af242d..1f4d4e780590 100644 --- a/browser/base/content/test/plugins/browser_CTP_context_menu.js +++ b/browser/base/content/test/plugins/browser_CTP_context_menu.js @@ -74,9 +74,12 @@ function test1() { // When the popupshown DOM event is fired, the actual showing of the popup // may still be pending. Clear the event loop before continuing so that // subsequently-opened popups aren't cancelled by accident. - let goToNext = function() { + let goToNext = function(aEvent) { window.document.removeEventListener("popupshown", goToNext, false); - executeSoon(test2); + executeSoon(function() { + test2(); + aEvent.target.hidePopup(); + }); }; window.document.addEventListener("popupshown", goToNext, false); EventUtils.synthesizeMouseAtCenter(plugin, diff --git a/toolkit/content/tests/widgets/chrome.ini b/toolkit/content/tests/widgets/chrome.ini index b04d0b453bf9..56db3ad8339f 100644 --- a/toolkit/content/tests/widgets/chrome.ini +++ b/toolkit/content/tests/widgets/chrome.ini @@ -5,6 +5,7 @@ support-files = window_menubar.xul [test_contextmenu_nested.xul] +[test_contextmenu_menugroup.xul] [test_editor_currentURI.xul] [test_menubar.xul] skip-if = os == 'mac' diff --git a/toolkit/content/tests/widgets/test_contextmenu_menugroup.xul b/toolkit/content/tests/widgets/test_contextmenu_menugroup.xul new file mode 100644 index 000000000000..119c431b97c1 --- /dev/null +++ b/toolkit/content/tests/widgets/test_contextmenu_menugroup.xul @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + +