3 <!-- ***** BEGIN LICENSE BLOCK *****
4 - Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 - The contents of this file are subject to the Mozilla Public License Version
7 - 1.1 (the "License"); you may not use this file except in compliance with
8 - the License. You may obtain a copy of the License at
9 - http://www.mozilla.org/MPL/
11 - Software distributed under the License is distributed on an "AS IS" basis,
12 - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 - for the specific language governing rights and limitations under the
16 - The Original Code is Native Menus Test code
18 - The Initial Developer of the Original Code is
19 - Mozilla Corporation.
20 - Portions created by the Initial Developer are Copyright (C) 2008
21 - the Initial Developer. All Rights Reserved.
24 - Josh Aas <josh@mozilla.com>
26 - Alternatively, the contents of this file may be used under the terms of
27 - either the GNU General Public License Version 2 or later (the "GPL"), or
28 - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 - in which case the provisions of the GPL or the LGPL are applicable instead
30 - of those above. If you wish to allow use of your version of this file only
31 - under the terms of either the GPL or the LGPL, and not to allow others to
32 - use your version of this file under the terms of the MPL, indicate your
33 - decision by deleting the provisions above and replace them with the notice
34 - and other provisions required by the GPL or the LGPL. If you do not delete
35 - the provisions above, a recipient may use your version of this file under
36 - the terms of any one of the MPL, the GPL or the LGPL.
38 - ***** END LICENSE BLOCK ***** -->
40 <?xml-stylesheet href=
"chrome://global/skin" type=
"text/css"?>
42 <window id=
"NativeMenuWindow"
43 xmlns=
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
47 title=
"Native Menu Test">
49 <command id=
"cmd_FooItem0" oncommand=
"executedCommandID = 'cmd_FooItem0';"/>
50 <command id=
"cmd_FooItem1" oncommand=
"executedCommandID = 'cmd_FooItem1';"/>
51 <command id=
"cmd_BarItem0" oncommand=
"executedCommandID = 'cmd_BarItem0';"/>
52 <command id=
"cmd_BarItem1" oncommand=
"executedCommandID = 'cmd_BarItem1';"/>
53 <command id=
"cmd_NewItem0" oncommand=
"executedCommandID = 'cmd_NewItem0';"/>
54 <command id=
"cmd_NewItem1" oncommand=
"executedCommandID = 'cmd_NewItem1';"/>
55 <command id=
"cmd_NewItem2" oncommand=
"executedCommandID = 'cmd_NewItem2';"/>
56 <command id=
"cmd_NewItem3" oncommand=
"executedCommandID = 'cmd_NewItem3';"/>
57 <command id=
"cmd_NewItem4" oncommand=
"executedCommandID = 'cmd_NewItem4';"/>
58 <command id=
"cmd_NewItem5" oncommand=
"executedCommandID = 'cmd_NewItem5';"/>
60 <!-- We do not modify any menus or menu items defined here in testing. These
61 serve as a baseline structure for us to test after other modifications.
62 We add children to the menubar defined here and test by modifying those
64 <menubar id=
"nativemenubar">
65 <menu id=
"foo" label=
"Foo">
67 <menuitem label=
"FooItem0" command=
"cmd_FooItem0"/>
68 <menuitem label=
"FooItem1" command=
"cmd_FooItem1"/>
72 <menuitem label=
"BarItem0" command=
"cmd_BarItem0"/>
73 <menuitem label=
"BarItem1" command=
"cmd_BarItem1"/>
80 <script type=
"application/javascript"><![CDATA[
82 function ok(condition, message) {
83 window.opener.wrappedJSObject.SimpleTest.ok(condition, message);
86 function onTestsFinished() {
88 window.opener.wrappedJSObject.SimpleTest.finish();
91 // We need to force a native menu reload before testing any dom changes
92 // because dom changes can affect the native menu system lazily.
93 function forceNativeMenuReload() {
94 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
95 var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
96 getInterface(Components.interfaces.nsIDOMWindowUtils);
98 utils.forceNativeMenuReload();
105 var executedCommandID =
"";
107 function testItem(location, targetID) {
108 netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
109 var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
110 getInterface(Components.interfaces.nsIDOMWindowUtils);
111 var correctCommandHandler = false;
113 utils.activateNativeMenuItemAt(location);
114 correctCommandHandler = executedCommandID == targetID;
120 executedCommandID =
"";
121 return correctCommandHandler;
125 function createXULMenuPopup() {
126 const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
127 var item = document.createElementNS(XUL_NS,
"menupopup");
131 function createXULMenu(aLabel) {
132 const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
133 var item = document.createElementNS(XUL_NS,
"menu");
134 item.setAttribute(
"label", aLabel);
138 function createXULMenuItem(aLabel, aCommandId) {
139 const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
140 var item = document.createElementNS(XUL_NS,
"menuitem");
141 item.setAttribute(
"label", aLabel);
142 item.setAttribute(
"command", aCommandId);
146 function runBaseMenuTests() {
147 return testItem(
"0|0",
"cmd_FooItem0") &&
148 testItem(
"0|1",
"cmd_FooItem1") &&
149 testItem(
"0|3|0",
"cmd_BarItem0") &&
150 testItem(
"0|3|1",
"cmd_BarItem1");
154 var _delayedOnLoad = function() {
155 // First let's run the base menu tests.
156 ok(runBaseMenuTests());
158 // Set up some nodes that we'll use.
159 var menubarNode = document.getElementById(
"nativemenubar");
160 var newMenu0 = createXULMenu(
"NewMenu0");
161 var newMenu1 = createXULMenu(
"NewMenu1");
162 var newMenuPopup0 = createXULMenuPopup();
163 var newMenuPopup1 = createXULMenuPopup();
164 var newMenuItem0 = createXULMenuItem(
"NewMenuItem0",
"cmd_NewItem0");
165 var newMenuItem1 = createXULMenuItem(
"NewMenuItem1",
"cmd_NewItem1");
166 var newMenuItem2 = createXULMenuItem(
"NewMenuItem2",
"cmd_NewItem2");
167 var newMenuItem3 = createXULMenuItem(
"NewMenuItem3",
"cmd_NewItem3");
168 var newMenuItem4 = createXULMenuItem(
"NewMenuItem4",
"cmd_NewItem4");
169 var newMenuItem5 = createXULMenuItem(
"NewMenuItem5",
"cmd_NewItem5");
171 // Create another submenu with hierarchy via DOM manipulation.
172 // ******************
173 // * Foo * NewMenu0 *
<- Menu bar
174 // ******************
176 // * NewMenuItem0 *
<- NewMenu0 submenu
181 // *******************************
182 // * NewMenu1
> * NewMenuItem3 *
<- NewMenu1 submenu
183 // *******************************
188 menubarNode.appendChild(newMenu0);
189 newMenu0.appendChild(newMenuPopup0);
190 newMenuPopup0.appendChild(newMenuItem0);
191 newMenuPopup0.appendChild(newMenuItem1);
192 newMenuPopup0.appendChild(newMenuItem2);
193 newMenuPopup0.appendChild(newMenu1);
194 newMenu1.appendChild(newMenuPopup1);
195 newMenuPopup1.appendChild(newMenuItem3);
196 newMenuPopup1.appendChild(newMenuItem4);
197 newMenuPopup1.appendChild(newMenuItem5);
200 var sa =
"Command handler(s) should have activated";
201 var sna =
"Command handler(s) should not have activated";
203 // Run basic tests again.
204 forceNativeMenuReload();
205 ok(runBaseMenuTests());
207 // Test middle items.
208 ok(testItem(
"1|1",
"cmd_NewItem1"), sa);
209 ok(testItem(
"1|3|1",
"cmd_NewItem4"), sa);
212 newMenu0.setAttribute(
"hidden",
"true");
213 forceNativeMenuReload();
214 ok(runBaseMenuTests(), sa); // the base menu should still be unhidden
215 ok(!testItem(
"1|0",
""), sna);
216 ok(!testItem(
"1|1",
""), sna);
217 ok(!testItem(
"1|2",
""), sna);
218 ok(!testItem(
"1|3|0",
""), sna);
219 ok(!testItem(
"1|3|1",
""), sna);
220 ok(!testItem(
"1|3|2",
""), sna);
223 newMenu0.setAttribute(
"hidden",
"false");
224 forceNativeMenuReload();
225 ok(runBaseMenuTests(), sa);
226 ok(testItem(
"1|0",
"cmd_NewItem0"), sa);
227 ok(testItem(
"1|1",
"cmd_NewItem1"), sa);
228 ok(testItem(
"1|2",
"cmd_NewItem2"), sa);
229 ok(testItem(
"1|3|0",
"cmd_NewItem3"), sa);
230 ok(testItem(
"1|3|1",
"cmd_NewItem4"), sa);
231 ok(testItem(
"1|3|2",
"cmd_NewItem5"), sa);
234 newMenuItem1.setAttribute(
"hidden",
"true");
235 newMenuItem4.setAttribute(
"hidden",
"true");
236 forceNativeMenuReload();
237 ok(runBaseMenuTests(), sa);
238 ok(testItem(
"1|0",
"cmd_NewItem0"), sa);
239 ok(testItem(
"1|1",
"cmd_NewItem2"), sa);
240 ok(!testItem(
"1|2",
""), sna);
241 ok(testItem(
"1|2|0",
"cmd_NewItem3"), sa);
242 ok(testItem(
"1|2|1",
"cmd_NewItem5"), sa);
243 ok(!testItem(
"1|2|2",
""), sna);
246 newMenuItem1.setAttribute(
"hidden",
"false");
247 newMenuItem4.setAttribute(
"hidden",
"false");
248 forceNativeMenuReload();
249 ok(runBaseMenuTests(), sa);
250 ok(testItem(
"1|0",
"cmd_NewItem0"), sa);
251 ok(testItem(
"1|1",
"cmd_NewItem1"), sa);
252 ok(testItem(
"1|2",
"cmd_NewItem2"), sa);
253 ok(testItem(
"1|3|0",
"cmd_NewItem3"), sa);
254 ok(testItem(
"1|3|1",
"cmd_NewItem4"), sa);
255 ok(testItem(
"1|3|2",
"cmd_NewItem5"), sa);
257 // At this point in the tests the state of the menus has been returned
258 // to the originally diagramed state.
261 menubarNode.removeChild(newMenu0);
262 forceNativeMenuReload();
263 ok(runBaseMenuTests(), sa);
264 ok(!testItem(
"1|0",
""), sna);
265 ok(!testItem(
"1|1",
""), sna);
266 ok(!testItem(
"1|2",
""), sna);
267 ok(!testItem(
"1|3|0",
""), sna);
268 ok(!testItem(
"1|3|1",
""), sna);
269 ok(!testItem(
"1|3|2",
""), sna);
270 // return state to original diagramed state
271 menubarNode.appendChild(newMenu0);
273 // Test for bug
447042, make sure that adding a menu node with no children
274 // to the menu bar and then adding another menu node with children works.
275 // Menus with no children don't get their native menu items shown and that
276 // caused internal arrays to get out of sync and an append crashed.
277 var tmpMenu0 = createXULMenu(
"tmpMenu0");
278 menubarNode.removeChild(newMenu0);
279 menubarNode.appendChild(tmpMenu0);
280 menubarNode.appendChild(newMenu0);
281 forceNativeMenuReload();
282 ok(runBaseMenuTests());
283 ok(testItem(
"1|0",
"cmd_NewItem0"), sa);
284 ok(testItem(
"1|1",
"cmd_NewItem1"), sa);
285 ok(testItem(
"1|2",
"cmd_NewItem2"), sa);
286 ok(testItem(
"1|3|0",
"cmd_NewItem3"), sa);
287 ok(testItem(
"1|3|1",
"cmd_NewItem4"), sa);
288 ok(testItem(
"1|3|2",
"cmd_NewItem5"), sa);
289 // return state to original diagramed state
290 menubarNode.removeChild(tmpMenu0);
295 setTimeout(_delayedOnLoad,
1000);