1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/widget/tests/native_menus_window.xul Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,277 @@ 1.4 +<?xml version="1.0"?> 1.5 + 1.6 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.7 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.9 + 1.10 +<?xml-stylesheet href="chrome://global/skin" type="text/css"?> 1.11 + 1.12 +<window id="NativeMenuWindow" 1.13 + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.14 + width="300" 1.15 + height="300" 1.16 + onload="onLoad();" 1.17 + title="Native Menu Test"> 1.18 + 1.19 + <command id="cmd_FooItem0" oncommand="executedCommandID = 'cmd_FooItem0';"/> 1.20 + <command id="cmd_FooItem1" oncommand="executedCommandID = 'cmd_FooItem1';"/> 1.21 + <command id="cmd_BarItem0" oncommand="executedCommandID = 'cmd_BarItem0';"/> 1.22 + <command id="cmd_BarItem1" oncommand="executedCommandID = 'cmd_BarItem1';"/> 1.23 + <command id="cmd_NewItem0" oncommand="executedCommandID = 'cmd_NewItem0';"/> 1.24 + <command id="cmd_NewItem1" oncommand="executedCommandID = 'cmd_NewItem1';"/> 1.25 + <command id="cmd_NewItem2" oncommand="executedCommandID = 'cmd_NewItem2';"/> 1.26 + <command id="cmd_NewItem3" oncommand="executedCommandID = 'cmd_NewItem3';"/> 1.27 + <command id="cmd_NewItem4" oncommand="executedCommandID = 'cmd_NewItem4';"/> 1.28 + <command id="cmd_NewItem5" oncommand="executedCommandID = 'cmd_NewItem5';"/> 1.29 + 1.30 + <!-- We do not modify any menus or menu items defined here in testing. These 1.31 + serve as a baseline structure for us to test after other modifications. 1.32 + We add children to the menubar defined here and test by modifying those 1.33 + children. --> 1.34 + <menubar id="nativemenubar"> 1.35 + <menu id="foo" label="Foo"> 1.36 + <menupopup> 1.37 + <menuitem label="FooItem0" command="cmd_FooItem0"/> 1.38 + <menuitem label="FooItem1" command="cmd_FooItem1"/> 1.39 + <menuseparator/> 1.40 + <menu label="Bar"> 1.41 + <menupopup> 1.42 + <menuitem label="BarItem0" command="cmd_BarItem0"/> 1.43 + <menuitem label="BarItem1" command="cmd_BarItem1"/> 1.44 + </menupopup> 1.45 + </menu> 1.46 + </menupopup> 1.47 + </menu> 1.48 + </menubar> 1.49 + 1.50 + <script type="application/javascript"><![CDATA[ 1.51 + 1.52 + function ok(condition, message) { 1.53 + window.opener.wrappedJSObject.SimpleTest.ok(condition, message); 1.54 + } 1.55 + 1.56 + function onTestsFinished() { 1.57 + window.close(); 1.58 + window.opener.wrappedJSObject.SimpleTest.finish(); 1.59 + } 1.60 + 1.61 + // Force a menu to update itself. All of the menus parents will be updated 1.62 + // as well. An empty string will force a complete menu system reload. 1.63 + function forceUpdateNativeMenuAt(location) { 1.64 + var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.65 + getInterface(Components.interfaces.nsIDOMWindowUtils); 1.66 + try { 1.67 + utils.forceUpdateNativeMenuAt(location); 1.68 + } 1.69 + catch (e) { 1.70 + dump(e + "\n"); 1.71 + } 1.72 + } 1.73 + 1.74 + var executedCommandID = ""; 1.75 + 1.76 + function testItem(location, targetID) { 1.77 + var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor). 1.78 + getInterface(Components.interfaces.nsIDOMWindowUtils); 1.79 + var correctCommandHandler = false; 1.80 + try { 1.81 + utils.activateNativeMenuItemAt(location); 1.82 + correctCommandHandler = executedCommandID == targetID; 1.83 + } 1.84 + catch (e) { 1.85 + dump(e + "\n"); 1.86 + } 1.87 + finally { 1.88 + executedCommandID = ""; 1.89 + return correctCommandHandler; 1.90 + } 1.91 + } 1.92 + 1.93 + function createXULMenuPopup() { 1.94 + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 1.95 + var item = document.createElementNS(XUL_NS, "menupopup"); 1.96 + return item; 1.97 + } 1.98 + 1.99 + function createXULMenu(aLabel) { 1.100 + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 1.101 + var item = document.createElementNS(XUL_NS, "menu"); 1.102 + item.setAttribute("label", aLabel); 1.103 + return item; 1.104 + } 1.105 + 1.106 + function createXULMenuItem(aLabel, aCommandId) { 1.107 + const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 1.108 + var item = document.createElementNS(XUL_NS, "menuitem"); 1.109 + item.setAttribute("label", aLabel); 1.110 + item.setAttribute("command", aCommandId); 1.111 + return item; 1.112 + } 1.113 + 1.114 + function runBaseMenuTests() { 1.115 + forceUpdateNativeMenuAt("0|3"); 1.116 + return testItem("0|0", "cmd_FooItem0") && 1.117 + testItem("0|1", "cmd_FooItem1") && 1.118 + testItem("0|3|0", "cmd_BarItem0") && 1.119 + testItem("0|3|1", "cmd_BarItem1"); 1.120 + } 1.121 + 1.122 + function onLoad() { 1.123 + var _delayedOnLoad = function() { 1.124 + // First let's run the base menu tests. 1.125 + ok(runBaseMenuTests()); 1.126 + 1.127 + // Set up some nodes that we'll use. 1.128 + var menubarNode = document.getElementById("nativemenubar"); 1.129 + var newMenu0 = createXULMenu("NewMenu0"); 1.130 + var newMenu1 = createXULMenu("NewMenu1"); 1.131 + var newMenuPopup0 = createXULMenuPopup(); 1.132 + var newMenuPopup1 = createXULMenuPopup(); 1.133 + var newMenuItem0 = createXULMenuItem("NewMenuItem0", "cmd_NewItem0"); 1.134 + var newMenuItem1 = createXULMenuItem("NewMenuItem1", "cmd_NewItem1"); 1.135 + var newMenuItem2 = createXULMenuItem("NewMenuItem2", "cmd_NewItem2"); 1.136 + var newMenuItem3 = createXULMenuItem("NewMenuItem3", "cmd_NewItem3"); 1.137 + var newMenuItem4 = createXULMenuItem("NewMenuItem4", "cmd_NewItem4"); 1.138 + var newMenuItem5 = createXULMenuItem("NewMenuItem5", "cmd_NewItem5"); 1.139 + 1.140 + // Create another submenu with hierarchy via DOM manipulation. 1.141 + // ****************** 1.142 + // * Foo * NewMenu0 * <- Menu bar 1.143 + // ****************** 1.144 + // **************** 1.145 + // * NewMenuItem0 * <- NewMenu0 submenu 1.146 + // **************** 1.147 + // * NewMenuItem1 * 1.148 + // **************** 1.149 + // * NewMenuItem2 * 1.150 + // ******************************* 1.151 + // * NewMenu1 > * NewMenuItem3 * <- NewMenu1 submenu 1.152 + // ******************************* 1.153 + // * NewMenuItem4 * 1.154 + // **************** 1.155 + // * NewMenuItem5 * 1.156 + // **************** 1.157 + newMenu0.appendChild(newMenuPopup0); 1.158 + newMenuPopup0.appendChild(newMenuItem0); 1.159 + newMenuPopup0.appendChild(newMenuItem1); 1.160 + newMenuPopup0.appendChild(newMenuItem2); 1.161 + newMenuPopup0.appendChild(newMenu1); 1.162 + newMenu1.appendChild(newMenuPopup1); 1.163 + newMenuPopup1.appendChild(newMenuItem3); 1.164 + newMenuPopup1.appendChild(newMenuItem4); 1.165 + newMenuPopup1.appendChild(newMenuItem5); 1.166 + //XXX - we have to append the menu to the top-level of the menu bar 1.167 + // only after constructing it. If we append before construction, it is 1.168 + // invalid because it has no children and we don't validate it if we add 1.169 + // children later. 1.170 + menubarNode.appendChild(newMenu0); 1.171 + forceUpdateNativeMenuAt("1|3"); 1.172 + // Run basic tests again. 1.173 + ok(runBaseMenuTests()); 1.174 + 1.175 + // Error strings. 1.176 + var sa = "Command handler(s) should have activated"; 1.177 + var sna = "Command handler(s) should not have activated"; 1.178 + 1.179 + // Test middle items. 1.180 + ok(testItem("1|1", "cmd_NewItem1"), sa); 1.181 + ok(testItem("1|3|1", "cmd_NewItem4"), sa); 1.182 + 1.183 + // Hide newMenu0. 1.184 + newMenu0.setAttribute("hidden", "true"); 1.185 + ok(runBaseMenuTests(), sa); // the base menu should still be unhidden 1.186 + ok(!testItem("1|0", ""), sna); 1.187 + ok(!testItem("1|1", ""), sna); 1.188 + ok(!testItem("1|2", ""), sna); 1.189 + ok(!testItem("1|3|0", ""), sna); 1.190 + ok(!testItem("1|3|1", ""), sna); 1.191 + ok(!testItem("1|3|2", ""), sna); 1.192 + 1.193 + // Show newMenu0. 1.194 + newMenu0.setAttribute("hidden", "false"); 1.195 + forceUpdateNativeMenuAt("1|3"); 1.196 + ok(runBaseMenuTests(), sa); 1.197 + ok(testItem("1|0", "cmd_NewItem0"), sa); 1.198 + ok(testItem("1|1", "cmd_NewItem1"), sa); 1.199 + ok(testItem("1|2", "cmd_NewItem2"), sa); 1.200 + ok(testItem("1|3|0", "cmd_NewItem3"), sa); 1.201 + ok(testItem("1|3|1", "cmd_NewItem4"), sa); 1.202 + ok(testItem("1|3|2", "cmd_NewItem5"), sa); 1.203 + 1.204 + // Hide items. 1.205 + newMenuItem1.setAttribute("hidden", "true"); 1.206 + newMenuItem4.setAttribute("hidden", "true"); 1.207 + forceUpdateNativeMenuAt("1|2"); 1.208 + ok(runBaseMenuTests(), sa); 1.209 + ok(testItem("1|0", "cmd_NewItem0"), sa); 1.210 + ok(testItem("1|1", "cmd_NewItem2"), sa); 1.211 + ok(!testItem("1|2", ""), sna); 1.212 + ok(testItem("1|2|0", "cmd_NewItem3"), sa); 1.213 + ok(testItem("1|2|1", "cmd_NewItem5"), sa); 1.214 + ok(!testItem("1|2|2", ""), sna); 1.215 + 1.216 + // Show items. 1.217 + newMenuItem1.setAttribute("hidden", "false"); 1.218 + newMenuItem4.setAttribute("hidden", "false"); 1.219 + forceUpdateNativeMenuAt("1|3"); 1.220 + ok(runBaseMenuTests(), sa); 1.221 + ok(testItem("1|0", "cmd_NewItem0"), sa); 1.222 + ok(testItem("1|1", "cmd_NewItem1"), sa); 1.223 + ok(testItem("1|2", "cmd_NewItem2"), sa); 1.224 + ok(testItem("1|3|0", "cmd_NewItem3"), sa); 1.225 + ok(testItem("1|3|1", "cmd_NewItem4"), sa); 1.226 + ok(testItem("1|3|2", "cmd_NewItem5"), sa); 1.227 + 1.228 + // At this point in the tests the state of the menus has been returned 1.229 + // to the originally diagramed state. 1.230 + 1.231 + // Remove menu. 1.232 + menubarNode.removeChild(newMenu0); 1.233 + ok(runBaseMenuTests(), sa); 1.234 + ok(!testItem("1|0", ""), sna); 1.235 + ok(!testItem("1|1", ""), sna); 1.236 + ok(!testItem("1|2", ""), sna); 1.237 + ok(!testItem("1|3|0", ""), sna); 1.238 + ok(!testItem("1|3|1", ""), sna); 1.239 + ok(!testItem("1|3|2", ""), sna); 1.240 + // return state to original diagramed state 1.241 + menubarNode.appendChild(newMenu0); 1.242 + 1.243 + // Test for bug 447042, make sure that adding a menu node with no children 1.244 + // to the menu bar and then adding another menu node with children works. 1.245 + // Menus with no children don't get their native menu items shown and that 1.246 + // caused internal arrays to get out of sync and an append crashed. 1.247 + var tmpMenu0 = createXULMenu("tmpMenu0"); 1.248 + menubarNode.removeChild(newMenu0); 1.249 + menubarNode.appendChild(tmpMenu0); 1.250 + menubarNode.appendChild(newMenu0); 1.251 + forceUpdateNativeMenuAt("1|3"); 1.252 + ok(runBaseMenuTests()); 1.253 + ok(testItem("1|0", "cmd_NewItem0"), sa); 1.254 + ok(testItem("1|1", "cmd_NewItem1"), sa); 1.255 + ok(testItem("1|2", "cmd_NewItem2"), sa); 1.256 + ok(testItem("1|3|0", "cmd_NewItem3"), sa); 1.257 + ok(testItem("1|3|1", "cmd_NewItem4"), sa); 1.258 + ok(testItem("1|3|2", "cmd_NewItem5"), sa); 1.259 + // return state to original diagramed state 1.260 + menubarNode.removeChild(tmpMenu0); 1.261 + delete tmpMenu0; 1.262 + 1.263 + // This test is basically a crash test for bug 433858. 1.264 + newMenuItem1.setAttribute("hidden", "true"); 1.265 + newMenuItem2.setAttribute("hidden", "true"); 1.266 + newMenu1.setAttribute("hidden", "true"); 1.267 + forceUpdateNativeMenuAt("1"); 1.268 + newMenuItem1.setAttribute("hidden", "false"); 1.269 + newMenuItem2.setAttribute("hidden", "false"); 1.270 + newMenu1.setAttribute("hidden", "false"); 1.271 + forceUpdateNativeMenuAt("1"); 1.272 + 1.273 + onTestsFinished(); 1.274 + } 1.275 + 1.276 + setTimeout(_delayedOnLoad, 1000); 1.277 + } 1.278 + 1.279 + ]]></script> 1.280 +</window>