Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // Is the currently opened tab focused?
6 function isTabFocused() {
7 let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
8 return Services.focus.focusedWindow == tabb.contentWindow;
9 }
11 function isChatFocused(chat) {
12 return SocialChatBar.chatbar._isChatFocused(chat);
13 }
15 function openChatViaUser() {
16 let sidebarDoc = document.getElementById("social-sidebar-browser").contentDocument;
17 let button = sidebarDoc.getElementById("chat-opener");
18 // Note we must use synthesizeMouseAtCenter() rather than calling
19 // .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
20 // to be true.
21 EventUtils.synthesizeMouseAtCenter(button, {}, sidebarDoc.defaultView);
22 }
24 function openChatViaSidebarMessage(port, data, callback) {
25 port.onmessage = function (e) {
26 if (e.data.topic == "chatbox-opened")
27 callback();
28 }
29 port.postMessage({topic: "test-chatbox-open", data: data});
30 }
32 function openChatViaWorkerMessage(port, data, callback) {
33 // sadly there is no message coming back to tell us when the chat has
34 // been opened, so we wait until one appears.
35 let chatbar = SocialChatBar.chatbar;
36 let numExpected = chatbar.childElementCount + 1;
37 port.postMessage({topic: "test-worker-chat", data: data});
38 waitForCondition(function() chatbar.childElementCount == numExpected,
39 function() {
40 // so the child has been added, but we don't know if it
41 // has been intialized - re-request it and the callback
42 // means it's done. Minimized, same as the worker.
43 SocialChatBar.openChat(SocialSidebar.provider,
44 data,
45 function() {
46 callback();
47 },
48 "minimized");
49 },
50 "No new chat appeared");
51 }
54 let isSidebarLoaded = false;
56 function startTestAndWaitForSidebar(callback) {
57 let doneCallback;
58 let port = SocialSidebar.provider.getWorkerPort();
59 function maybeCallback() {
60 if (!doneCallback)
61 callback(port);
62 doneCallback = true;
63 }
64 port.onmessage = function(e) {
65 let topic = e.data.topic;
66 switch (topic) {
67 case "got-sidebar-message":
68 // if sidebar loaded too fast, we need a backup ping
69 case "got-isVisible-response":
70 isSidebarLoaded = true;
71 maybeCallback();
72 break;
73 case "test-init-done":
74 if (isSidebarLoaded)
75 maybeCallback();
76 else
77 port.postMessage({topic: "test-isVisible"});
78 break;
79 }
80 }
81 port.postMessage({topic: "test-init"});
82 }
84 let manifest = { // normal provider
85 name: "provider 1",
86 origin: "https://example.com",
87 sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
88 workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
89 iconURL: "https://example.com/browser/browser/base/content/test/general/moz.png"
90 };
92 function test() {
93 waitForExplicitFinish();
95 // Note that (probably) due to bug 604289, if a tab is focused but the
96 // focused element is null, our chat windows can "steal" focus. This is
97 // avoided if we explicitly focus an element in the tab.
98 // So we load a page with an <input> field and focus that before testing.
99 let url = "data:text/html;charset=utf-8," + encodeURI('<input id="theinput">');
100 let tab = gBrowser.selectedTab = gBrowser.addTab(url, {skipAnimation: true});
101 tab.linkedBrowser.addEventListener("load", function tabLoad(event) {
102 tab.linkedBrowser.removeEventListener("load", tabLoad, true);
103 // before every test we focus the input field.
104 let preSubTest = function(cb) {
105 // XXX - when bug 604289 is fixed it should be possible to just do:
106 // tab.linkedBrowser.contentWindow.focus()
107 // but instead we must do:
108 tab.linkedBrowser.contentDocument.getElementById("theinput").focus();
109 waitForCondition(function() isTabFocused(), cb, "tab should have focus");
110 }
111 let postSubTest = function(cb) {
112 window.SocialChatBar.chatbar.removeAll();
113 cb();
114 }
115 // and run the tests.
116 runSocialTestWithProvider(manifest, function (finishcb) {
117 SocialSidebar.show();
118 runSocialTests(tests, preSubTest, postSubTest, function () {
119 finishcb();
120 });
121 });
122 }, true);
123 registerCleanupFunction(function() {
124 gBrowser.removeTab(tab);
125 });
127 }
129 var tests = {
130 // In this test the worker asks the sidebar to open a chat. As that means
131 // we aren't handling user-input we will not focus the chatbar.
132 // Then we do it again - should still not be focused.
133 // Then we perform a user-initiated request - it should get focus.
134 testNoFocusWhenViaWorker: function(next) {
135 startTestAndWaitForSidebar(function(port) {
136 openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
137 ok(true, "got chatbox message");
138 is(SocialChatBar.chatbar.childElementCount, 1, "exactly 1 chat open");
139 ok(isTabFocused(), "tab should still be focused");
140 // re-request the same chat via a message.
141 openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
142 is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
143 ok(isTabFocused(), "tab should still be focused");
144 // re-request the same chat via user event.
145 openChatViaUser();
146 waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
147 function() {
148 is(SocialChatBar.chatbar.childElementCount, 1, "still exactly 1 chat open");
149 is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat should be selected");
150 next();
151 }, "chat should be focused");
152 });
153 });
154 });
155 },
157 // In this test we arrange for the sidebar to open the chat via a simulated
158 // click. This should cause the new chat to be opened and focused.
159 testFocusWhenViaUser: function(next) {
160 startTestAndWaitForSidebar(function(port) {
161 openChatViaUser();
162 ok(SocialChatBar.chatbar.firstElementChild, "chat opened");
163 waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
164 function() {
165 is(SocialChatBar.chatbar.selectedChat, SocialChatBar.chatbar.firstElementChild, "chat is selected");
166 next();
167 }, "chat should be focused");
168 });
169 },
171 // Open a chat via the worker - it will open and not have focus.
172 // Then open the same chat via a sidebar message - it will be restored but
173 // should still not have grabbed focus.
174 testNoFocusOnAutoRestore: function(next) {
175 const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html?id=1";
176 let chatbar = SocialChatBar.chatbar;
177 startTestAndWaitForSidebar(function(port) {
178 openChatViaWorkerMessage(port, chatUrl, function() {
179 is(chatbar.childElementCount, 1, "exactly 1 chat open");
180 // bug 865086 opening minimized still sets the window as selected
181 todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
182 ok(isTabFocused(), "tab should be focused");
183 openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
184 is(chatbar.childElementCount, 1, "still 1 chat open");
185 ok(!chatbar.firstElementChild.minimized, "chat no longer minimized");
186 // bug 865086 because we marked it selected on open, it still is
187 todo(chatbar.selectedChat != chatbar.firstElementChild, "chat is not selected");
188 ok(isTabFocused(), "tab should still be focused");
189 next();
190 });
191 });
192 });
193 },
195 // Here we open a chat, which will not be focused. Then we minimize it and
196 // restore it via a titlebar clock - it should get focus at that point.
197 testFocusOnExplicitRestore: function(next) {
198 startTestAndWaitForSidebar(function(port) {
199 openChatViaSidebarMessage(port, {stealFocus: 1}, function() {
200 ok(true, "got chatbox message");
201 ok(isTabFocused(), "tab should still be focused");
202 let chatbox = SocialChatBar.chatbar.firstElementChild;
203 ok(chatbox, "chat opened");
204 chatbox.minimized = true;
205 ok(isTabFocused(), "tab should still be focused");
206 // pretend we clicked on the titlebar
207 chatbox.onTitlebarClick({button: 0});
208 waitForCondition(function() isChatFocused(SocialChatBar.chatbar.selectedChat),
209 function() {
210 ok(!chatbox.minimized, "chat should have been restored");
211 ok(isChatFocused(chatbox), "chat should be focused");
212 is(chatbox, SocialChatBar.chatbar.selectedChat, "chat is marked selected");
213 next();
214 }, "chat should have focus");
215 });
216 });
217 },
219 // Open 2 chats and give 1 focus. Minimize the focused one - the second
220 // should get focus.
221 testMinimizeFocused: function(next) {
222 let chatbar = SocialChatBar.chatbar;
223 startTestAndWaitForSidebar(function(port) {
224 openChatViaSidebarMessage(port, {stealFocus: 1, id: 1}, function() {
225 let chat1 = chatbar.firstElementChild;
226 openChatViaSidebarMessage(port, {stealFocus: 1, id: 2}, function() {
227 is(chatbar.childElementCount, 2, "exactly 2 chats open");
228 let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
229 chatbar.selectedChat = chat1;
230 chatbar.focus();
231 waitForCondition(function() isChatFocused(chat1),
232 function() {
233 is(chat1, SocialChatBar.chatbar.selectedChat, "chat1 is marked selected");
234 isnot(chat2, SocialChatBar.chatbar.selectedChat, "chat2 is not marked selected");
235 chat1.minimized = true;
236 waitForCondition(function() isChatFocused(chat2),
237 function() {
238 // minimizing the chat with focus should give it to another.
239 isnot(chat1, SocialChatBar.chatbar.selectedChat, "chat1 is not marked selected");
240 is(chat2, SocialChatBar.chatbar.selectedChat, "chat2 is marked selected");
241 next();
242 }, "chat2 should have focus");
243 }, "chat1 should have focus");
244 });
245 });
246 });
247 },
249 // Open 2 chats, select (but not focus) one, then re-request it be
250 // opened via a message. Focus should not move.
251 testReopenNonFocused: function(next) {
252 let chatbar = SocialChatBar.chatbar;
253 startTestAndWaitForSidebar(function(port) {
254 openChatViaSidebarMessage(port, {id: 1}, function() {
255 let chat1 = chatbar.firstElementChild;
256 openChatViaSidebarMessage(port, {id: 2}, function() {
257 let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
258 chatbar.selectedChat = chat2;
259 // tab still has focus
260 ok(isTabFocused(), "tab should still be focused");
261 // re-request the first.
262 openChatViaSidebarMessage(port, {id: 1}, function() {
263 is(chatbar.selectedChat, chat1, "chat1 now selected");
264 ok(isTabFocused(), "tab should still be focused");
265 next();
266 });
267 });
268 });
269 });
270 },
272 // Open 2 chats, select and focus the second. Pressing the TAB key should
273 // cause focus to move between all elements in our chat window before moving
274 // to the next chat window.
275 testTab: function(next) {
276 function sendTabAndWaitForFocus(chat, eltid, callback) {
277 // ideally we would use the 'focus' event here, but that doesn't work
278 // as expected for the iframe - the iframe itself never gets the focus
279 // event (apparently the sub-document etc does.)
280 // So just poll for the correct element getting focus...
281 let doc = chat.contentDocument;
282 EventUtils.sendKey("tab");
283 waitForCondition(function() {
284 let elt = eltid ? doc.getElementById(eltid) : doc.documentElement;
285 return doc.activeElement == elt;
286 }, callback, "element " + eltid + " never got focus");
287 }
289 let chatbar = SocialChatBar.chatbar;
290 startTestAndWaitForSidebar(function(port) {
291 openChatViaSidebarMessage(port, {id: 1}, function() {
292 let chat1 = chatbar.firstElementChild;
293 openChatViaSidebarMessage(port, {id: 2}, function() {
294 let chat2 = chat1.nextElementSibling || chat1.previousElementSibling;
295 chatbar.selectedChat = chat2;
296 chatbar.focus();
297 waitForCondition(function() isChatFocused(chatbar.selectedChat),
298 function() {
299 // Our chats have 3 focusable elements, so it takes 4 TABs to move
300 // to the new chat.
301 sendTabAndWaitForFocus(chat2, "input1", function() {
302 is(chat2.contentDocument.activeElement.getAttribute("id"), "input1",
303 "first input field has focus");
304 ok(isChatFocused(chat2), "new chat still focused after first tab");
305 sendTabAndWaitForFocus(chat2, "input2", function() {
306 ok(isChatFocused(chat2), "new chat still focused after tab");
307 is(chat2.contentDocument.activeElement.getAttribute("id"), "input2",
308 "second input field has focus");
309 sendTabAndWaitForFocus(chat2, "iframe", function() {
310 ok(isChatFocused(chat2), "new chat still focused after tab");
311 is(chat2.contentDocument.activeElement.getAttribute("id"), "iframe",
312 "iframe has focus");
313 // this tab now should move to the next chat, but focus the
314 // document element itself (hence the null eltid)
315 sendTabAndWaitForFocus(chat1, null, function() {
316 ok(isChatFocused(chat1), "first chat is focused");
317 next();
318 });
319 });
320 });
321 });
322 }, "chat should have focus");
323 });
324 });
325 });
326 },
328 // Open a chat and focus an element other than the first. Move focus to some
329 // other item (the tab itself in this case), then focus the chatbar - the
330 // same element that was previously focused should still have focus.
331 testFocusedElement: function(next) {
332 let chatbar = SocialChatBar.chatbar;
333 startTestAndWaitForSidebar(function(port) {
334 openChatViaUser();
335 let chat = chatbar.firstElementChild;
336 // need to wait for the content to load before we can focus it.
337 chat.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
338 chat.removeEventListener("DOMContentLoaded", DOMContentLoaded);
339 chat.contentDocument.getElementById("input2").focus();
340 waitForCondition(function() isChatFocused(chat),
341 function() {
342 is(chat.contentDocument.activeElement.getAttribute("id"), "input2",
343 "correct input field has focus");
344 // set focus to the tab.
345 let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
346 Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
347 waitForCondition(function() isTabFocused(),
348 function() {
349 chatbar.focus();
350 waitForCondition(function() isChatFocused(chat),
351 function() {
352 is(chat.contentDocument.activeElement.getAttribute("id"), "input2",
353 "correct input field still has focus");
354 next();
355 }, "chat took focus");
356 }, "tab has focus");
357 }, "chat took focus");
358 });
359 });
360 },
361 };