Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 <?xml version="1.0"?>
2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
5 <window title="Context Menu on List Tests"
6 onload="setTimeout(startTest, 0);"
7 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
9 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
10 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
12 <spacer height="5"/>
14 <hbox style="padding-left: 10px;">
15 <spacer width="5"/>
16 <richlistbox id="list" context="themenu" style="padding: 0;" oncontextmenu="checkContextMenu(event)">
17 <richlistitem id="item1" style="padding-top: 3px; margin: 0;"><button label="One"/></richlistitem>
18 <richlistitem id="item2" height="22"><checkbox label="Checkbox"/></richlistitem>
19 <richlistitem id="item3"><button label="Three"/></richlistitem>
20 <richlistitem id="item4"><checkbox label="Four"/></richlistitem>
21 </richlistbox>
23 <tree id="tree" rows="5" flex="1" context="themenu" style="-moz-appearance: none; border: 0">
24 <treecols>
25 <treecol label="Name" flex="1"/>
26 <splitter class="tree-splitter"/>
27 <treecol label="Moons"/>
28 </treecols>
29 <treechildren id="treechildren">
30 <treeitem>
31 <treerow>
32 <treecell label="Mercury"/>
33 <treecell label="0"/>
34 </treerow>
35 </treeitem>
36 <treeitem>
37 <treerow>
38 <treecell label="Venus"/>
39 <treecell label="0"/>
40 </treerow>
41 </treeitem>
42 <treeitem>
43 <treerow>
44 <treecell label="Earth"/>
45 <treecell label="1"/>
46 </treerow>
47 </treeitem>
48 <treeitem>
49 <treerow>
50 <treecell label="Mars"/>
51 <treecell label="2"/>
52 </treerow>
53 </treeitem>
54 </treechildren>
55 </tree>
57 <menu id="menu" label="Menu">
58 <menupopup id="menupopup" onpopupshown="menuTests()" onpopuphidden="nextTest()"
59 oncontextmenu="checkContextMenuForMenu(event)">
60 <menuitem id="menu1" label="Menu 1"/>
61 <menuitem id="menu2" label="Menu 2"/>
62 <menuitem id="menu3" label="Menu 3"/>
63 </menupopup>
64 </menu>
66 </hbox>
68 <menupopup id="themenu" onpopupshowing="if (gTestId == -1) event.preventDefault()"
69 onpopupshown="checkPopup()" onpopuphidden="setTimeout(nextTest, 0);">
70 <menuitem label="Item"/>
71 </menupopup>
73 <script class="testbody" type="application/javascript">
74 <![CDATA[
76 SimpleTest.waitForExplicitFinish();
78 var gTestId = -1;
79 var gTestElement = "list";
80 var gSelectionStep = 0;
81 var gContextMenuFired = false;
83 function startTest()
84 {
85 // first, check if the richlistbox selection changes on a contextmenu mouse event
86 var element = $("list");
87 synthesizeMouse(element.getItemAtIndex(3), 7, 1, { type : "mousedown", button: 2, ctrlKey: true });
88 synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
90 gSelectionStep++;
91 synthesizeMouse(element.getItemAtIndex(1), 7, 1, { type : "mousedown", button: 2, ctrlKey: true, shiftKey: true });
92 synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
94 gSelectionStep++;
95 synthesizeMouse(element.getItemAtIndex(1), 7, 1, { type : "mousedown", button: 2 });
96 synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
98 $("menu").open = true;
99 }
101 function menuTests()
102 {
103 gSelectionStep = 0;
104 var element = $("menu");
105 synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
106 is(gContextMenuFired, true, "context menu fired when menu open");
108 gSelectionStep = 1;
109 $("menu").boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject).activeChild = $("menu2");
110 synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
112 $("menu").open = false;
113 }
115 function nextTest()
116 {
117 gTestId++;
118 if (gTestId > 2) {
119 if (gTestElement == "list") {
120 gTestElement = "tree";
121 gTestId = 0;
122 }
123 else {
124 SimpleTest.finish();
125 return;
126 }
127 }
128 var element = $(gTestElement);
129 element.focus();
130 if (gTestId == 0) {
131 if (gTestElement == "list")
132 element.selectedIndex = 2;
133 element.currentIndex = 2;
134 synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
135 }
136 else if (gTestId == 1) {
137 synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
138 }
139 else {
140 element.currentIndex = -1;
141 element.selectedIndex = -1;
142 synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
143 }
144 }
146 // This is nasty so I'd better explain what's going on.
147 // The basic problem is that the synthetic mouse coordinate generated
148 // by DOMWindowUtils.sendMouseEvent and also the synthetic mouse coordinate
149 // generated internally when contextmenu events are redirected to the focused
150 // element are rounded to the nearest device pixel. But this rounding is done
151 // while the coordinates are relative to the nearest widget. When this test
152 // is run in the mochitest harness, the nearest widget is the main mochitest
153 // window, and our document can have a fractional position within that
154 // mochitest window. So when we round coordinates for comparison in this
155 // test, we need to do so very carefully, especially if the target element
156 // also has a fractional position within our document.
157 //
158 // For example, if the y-offset of our containing IFRAME is 100.4px,
159 // and the offset of our expected point is 10.3px in our document, the actual
160 // mouse event is dispatched to round(110.7) == 111px. This comes back
161 // with a clientY of round(111 - 100.4) == round(10.6) == 11. This is not
162 // equal to round(10.3) as you might expect.
164 function isRoundedX(a, b, msg)
165 {
166 is(Math.round(a + mozInnerScreenX), Math.round(b + mozInnerScreenX), msg);
167 }
169 function isRoundedY(a, b, msg)
170 {
171 is(Math.round(a + mozInnerScreenY), Math.round(b + mozInnerScreenY), msg);
172 }
174 function checkContextMenu(event)
175 {
176 var rect = $(gTestElement).getBoundingClientRect();
178 var frombase = (gTestId == -1 || gTestId == 1);
179 if (!frombase)
180 rect = event.originalTarget.getBoundingClientRect();
181 var left = frombase ? rect.left + 7 : rect.left;
182 var top = frombase ? rect.top + 4 : rect.bottom;
184 isRoundedX(event.clientX, left, gTestElement + " clientX " + gSelectionStep + " " + gTestId + "," + frombase);
185 isRoundedY(event.clientY, top, gTestElement + " clientY " + gSelectionStep + " " + gTestId);
186 ok(event.screenX > left, gTestElement + " screenX " + gSelectionStep + " " + gTestId);
187 ok(event.screenY > top, gTestElement + " screenY " + gSelectionStep + " " + gTestId);
189 // context menu from mouse click
190 switch (gTestId) {
191 case -1:
192 var expected = gSelectionStep == 2 ? 1 : (navigator.platform.indexOf("Mac") >= 0 ? 3 : 0);
193 is($(gTestElement).selectedIndex, expected, "index after click " + gSelectionStep);
194 break;
195 case 0:
196 if (gTestElement == "list")
197 is(event.originalTarget, $("item3"), "list selection target");
198 else
199 is(event.originalTarget, $("treechildren"), "tree selection target");
200 break;
201 case 1:
202 is(event.originalTarget.id, $("item1").id, "list mouse selection target");
203 break;
204 case 2:
205 is(event.originalTarget, $("list"), "list no selection target");
206 break;
207 }
208 }
210 function checkContextMenuForMenu(event)
211 {
212 gContextMenuFired = true;
214 var popuprect = (gSelectionStep ? $("menu2") : $("menupopup")).getBoundingClientRect();
215 is(event.clientX, Math.round(popuprect.left), "menu left " + gSelectionStep);
216 // the clientY is off by one sometimes on Windows (when loaded in the testing iframe
217 // but not when loaded separately) so just check for both cases for now
218 ok(event.clientY == Math.round(popuprect.bottom) ||
219 event.clientY - 1 == Math.round(popuprect.bottom), "menu top " + gSelectionStep);
220 }
222 function checkPopup()
223 {
224 var menurect = $("themenu").getBoundingClientRect();
226 if (gTestId == 0) {
227 if (gTestElement == "list") {
228 var itemrect = $("item3").getBoundingClientRect();
229 isRoundedX(menurect.left, itemrect.left + 2,
230 "list selection keyboard left");
231 isRoundedY(menurect.top, itemrect.bottom + 2,
232 "list selection keyboard top");
233 }
234 else {
235 var tree = $("tree");
236 var bodyrect = $("treechildren").getBoundingClientRect();
237 isRoundedX(menurect.left, bodyrect.left + 2,
238 "tree selection keyboard left");
239 isRoundedY(menurect.top, bodyrect.top +
240 tree.treeBoxObject.rowHeight * 3 + 2,
241 "tree selection keyboard top");
242 }
243 }
244 else if (gTestId == 1) {
245 // activating a context menu with the mouse from position (7, 1).
246 // Add 2 pixels to these values as context menus are offset by 2 pixels
247 // so that they don't appear exactly only the menu making them easier to
248 // dismiss. See nsXULPopupListener.
249 var elementrect = $(gTestElement).getBoundingClientRect();
250 isRoundedX(menurect.left, elementrect.left + 9,
251 gTestElement + " mouse left");
252 isRoundedY(menurect.top, elementrect.top + 6,
253 gTestElement + " mouse top");
254 }
255 else {
256 var elementrect = $(gTestElement).getBoundingClientRect();
257 isRoundedX(menurect.left, elementrect.left + 2,
258 gTestElement + " no selection keyboard left");
259 isRoundedY(menurect.top, elementrect.bottom + 2,
260 gTestElement + " no selection keyboard top");
261 }
263 $("themenu").hidePopup();
264 }
266 ]]>
267 </script>
269 <body xmlns="http://www.w3.org/1999/xhtml">
270 <p id="display">
271 </p>
272 <div id="content" style="display: none">
273 </div>
274 <pre id="test">
275 </pre>
276 </body>
278 </window>