browser/base/content/test/social/browser_social_chatwindowfocus.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial