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.

     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 };

mercurial