Bug 1154277: Part 3 - implement test changes to work in e10s mode as well. r=mixedpuppy,Standard8

This commit is contained in:
Mike de Boer 2016-02-04 13:42:10 +01:00
parent f72d46f1cc
commit c01b4f7990
9 changed files with 168 additions and 90 deletions

View File

@ -99,10 +99,12 @@ SocialErrorListener = {
break;
case "Social:EnsureFocus":
Services.focus.focusedWindow = content;
sendAsyncMessage("Social:FocusEnsured");
break;
case "Social:EnsureFocusElement":
let fm = Services.focus;
fm.moveFocus(document.defaultView, null, fm.MOVEFOCUS_FIRST, fm.FLAG_NOSCROLL);
sendAsyncMessage("Social:FocusEnsured");
break;
case "Social:HookWindowCloseForPanelClose":
// We allow window.close() to close the panel, so add an event handler for

View File

@ -7,3 +7,4 @@ support-files =
[browser_chatwindow.js]
[browser_focus.js]
[browser_tearoff.js]
skip-if = true # Bug 1245805 - tearing off chat windows causes a browser crash.

View File

@ -25,9 +25,7 @@ add_chat_task(function* testOpenCloseChat() {
is(chatbar.selectedChat, null);
// We check the content gets an unload event as we close it.
let promiseClosed = promiseOneEvent(chatbox.content, "unload", true);
chatbox.close();
yield promiseClosed;
});
// In this case we open a chat minimized, then request the same chat again
@ -82,8 +80,9 @@ add_chat_task(function* testOpenTwiceCallbacks() {
// Bug 817782 - check chats work in new top-level windows.
add_chat_task(function* testSecondTopLevelWindow() {
const chatUrl = "http://example.com";
let secondWindow = OpenBrowserWindow();
yield promiseOneEvent(secondWindow, "load");
let winPromise = BrowserTestUtils.waitForNewWindow();
OpenBrowserWindow();
let secondWindow = yield winPromise;
yield promiseOpenChat(chatUrl);
// the chat was created - let's make sure it was created in the second window.
Assert.equal(numChatsInWindow(window), 0, "main window has no chats");

View File

@ -51,26 +51,38 @@ add_chat_task(function* testDefaultFocus() {
});
// Test default focus via user input.
add_chat_task(function* testDefaultFocus() {
add_chat_task(function* testDefaultFocusUserInput() {
todo(false, "BrowserTestUtils.synthesizeMouseAtCenter doesn't move the user " +
"focus to the chat window, even though we're recording a click correctly.");
return;
yield setUp();
let tab = gBrowser.selectedTab;
let browser = gBrowser.selectedTab.linkedBrowser;
let mm = browser.messageManager;
let deferred = Promise.defer();
let button = tab.linkedBrowser.contentDocument.getElementById("chat-opener");
button.addEventListener("click", function onclick() {
button.removeEventListener("click", onclick);
promiseOpenChat("http://example.com").then(
chat => deferred.resolve(chat)
);
})
mm.addMessageListener("ChatOpenerClicked", function handler() {
mm.removeMessageListener("ChatOpenerClicked", handler);
promiseOpenChat("http://example.com").then(chat => deferred.resolve(chat));
});
yield ContentTask.spawn(browser, null, function* () {
let button = content.document.getElementById("chat-opener");
button.addEventListener("click", function onclick() {
button.removeEventListener("click", onclick);
sendAsyncMessage("ChatOpenerClicked");
});
});
// Note we must use synthesizeMouseAtCenter() rather than calling
// .click() directly as this causes nsIDOMWindowUtils.isHandlingUserInput
// to be true.
EventUtils.synthesizeMouseAtCenter(button, {}, button.ownerDocument.defaultView);
yield BrowserTestUtils.synthesizeMouseAtCenter("#chat-opener", {}, browser);
let chat = yield deferred.promise;
// we use the default focus behaviour but the chat was opened via user input,
// so the chat should be focused.
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
yield promiseWaitForCondition(() => !isTabFocused());
Assert.ok(!isTabFocused(), "the tab should have lost focus.");
Assert.ok(isChatFocused(chat), "the chat should have got focus.");
});
@ -82,6 +94,7 @@ add_chat_task(function* testExplicitFocus() {
// we use the default focus behaviour, which means that because this was
// not the direct result of user action the chat should not be focused.
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
yield promiseWaitForCondition(() => !isTabFocused());
Assert.ok(!isTabFocused(), "the tab should have lost focus.");
Assert.ok(isChatFocused(chat), "the chat should have got focus.");
});
@ -114,7 +127,7 @@ add_chat_task(function* testFocusOnExplicitRestore() {
Assert.ok(isTabFocused(), "tab should still be focused");
Assert.ok(!isChatFocused(chat), "the chat should not be focused.");
let promise = promiseOneEvent(chat.contentWindow, "focus");
let promise = promiseOneMessage(chat.content, "Social:FocusEnsured");
// pretend we clicked on the titlebar
chat.onTitlebarClick({button: 0});
yield promise; // wait for focus event.
@ -131,13 +144,18 @@ add_chat_task(function* testMinimizeFocused() {
let chat2 = yield promiseOpenChat("http://example.com#2");
Assert.equal(numChatsInWindow(window), 2, "2 chats open");
Assert.strictEqual(chatbar.selectedChat, chat2, "chat2 is selected");
let promise = promiseOneEvent(chat1.contentWindow, "focus");
let promise = promiseOneMessage(chat1.content, "Social:FocusEnsured");
chatbar.selectedChat = chat1;
chatbar.focus();
yield promise; // wait for chat1 to get focus.
Assert.strictEqual(chat1, chatbar.selectedChat, "chat1 is marked selected");
Assert.notStrictEqual(chat2, chatbar.selectedChat, "chat2 is not marked selected");
promise = promiseOneEvent(chat2.contentWindow, "focus");
todo(false, "Bug 1245803 should re-enable the test below to have a chat window " +
"re-gain focus when another chat window is minimized.");
return;
promise = promiseOneMessage(chat2.content, "Social:FocusEnsured");
chat1.minimized = true;
yield promise; // wait for chat2 to get focus.
Assert.notStrictEqual(chat1, chatbar.selectedChat, "chat1 is not marked selected");
@ -151,37 +169,42 @@ add_chat_task(function* testTab() {
yield setUp();
function sendTabAndWaitForFocus(chat, eltid) {
let doc = chat.contentDocument;
EventUtils.sendKey("tab");
// ideally we would use the 'focus' event here, but that doesn't work
// as expected for the iframe - the iframe itself never gets the focus
// event (apparently the sub-document etc does.)
// So just poll for the correct element getting focus...
let deferred = Promise.defer();
let tries = 0;
let interval = setInterval(function() {
if (tries >= 30) {
clearInterval(interval);
deferred.reject("never got focus");
return;
}
tries ++;
let elt = eltid ? doc.getElementById(eltid) : doc.documentElement;
if (doc.activeElement == elt) {
clearInterval(interval);
deferred.resolve();
}
info("retrying wait for focus: " + tries);
info("(the active element is " + doc.activeElement + "/" + doc.activeElement.getAttribute("id") + ")");
}, 100);
info("waiting for element " + eltid + " to get focus");
return deferred.promise;
return ContentTask.spawn(chat.content, { eltid: eltid }, function* (args) {
let doc = content.document;
// ideally we would use the 'focus' event here, but that doesn't work
// as expected for the iframe - the iframe itself never gets the focus
// event (apparently the sub-document etc does.)
// So just poll for the correct element getting focus...
yield new Promise(function(resolve, reject) {
let tries = 0;
let interval = content.setInterval(function() {
if (tries >= 30) {
clearInterval(interval);
reject("never got focus");
return;
}
tries++;
let elt = args.eltid ? doc.getElementById(args.eltid) : doc.documentElement;
if (doc.activeElement == elt) {
content.clearInterval(interval);
resolve();
}
info("retrying wait for focus: " + tries);
info("(the active element is " + doc.activeElement + "/" +
doc.activeElement.getAttribute("id") + ")");
}, 100);
info("waiting for element " + args.eltid + " to get focus");
});
});
}
let chat1 = yield promiseOpenChat(CHAT_URL + "#1");
let chat2 = yield promiseOpenChat(CHAT_URL + "#2");
chatbar.selectedChat = chat2;
let promise = promiseOneEvent(chat2.contentWindow, "focus");
let promise = promiseOneMessage(chat2.content, "Social:FocusEnsured");
chatbar.focus();
info("waiting for second chat to get focus");
yield promise;
@ -189,19 +212,13 @@ add_chat_task(function* testTab() {
// Our chats have 3 focusable elements, so it takes 4 TABs to move
// to the new chat.
yield sendTabAndWaitForFocus(chat2, "input1");
Assert.equal(chat2.contentDocument.activeElement.getAttribute("id"), "input1",
"first input field has focus");
Assert.ok(isChatFocused(chat2), "new chat still focused after first tab");
yield sendTabAndWaitForFocus(chat2, "input2");
Assert.ok(isChatFocused(chat2), "new chat still focused after tab");
Assert.equal(chat2.contentDocument.activeElement.getAttribute("id"), "input2",
"second input field has focus");
yield sendTabAndWaitForFocus(chat2, "iframe");
Assert.ok(isChatFocused(chat2), "new chat still focused after tab");
Assert.equal(chat2.contentDocument.activeElement.getAttribute("id"), "iframe",
"iframe has focus");
// this tab now should move to the next chat, but focus the
// document element itself (hence the null eltid)
@ -218,7 +235,9 @@ add_chat_task(function* testFocusedElement() {
// open a chat with focus requested.
let chat = yield promiseOpenChat(CHAT_URL, undefined, true);
chat.contentDocument.getElementById("input2").focus();
yield ContentTask.spawn(chat.content, null, function* () {
content.document.getElementById("input2").focus();
});
// set focus to the tab.
let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
@ -226,10 +245,12 @@ add_chat_task(function* testFocusedElement() {
Services.focus.moveFocus(tabb.contentWindow, null, Services.focus.MOVEFOCUS_ROOT, 0);
yield promise;
promise = promiseOneEvent(chat.contentWindow, "focus");
promise = promiseOneMessage(chat.content, "Social:FocusEnsured");
chatbar.focus();
yield promise;
Assert.equal(chat.contentDocument.activeElement.getAttribute("id"), "input2",
"correct input field still has focus");
yield ContentTask.spawn(chat.content, null, function* () {
is(content.document.activeElement.getAttribute("id"), "input2",
"correct input field still has focus");
});
});

View File

@ -19,7 +19,7 @@ function promiseNewWindowLoaded() {
domwindow.addEventListener("load", function _load(event) {
let doc = domwindow.document;
if (event.target != doc)
return;
return;
domwindow.removeEventListener("load", _load);
deferred.resolve(domwindow);
});
@ -32,18 +32,21 @@ add_chat_task(function* testTearoffChat() {
let chatbox = yield promiseOpenChat("http://example.com");
Assert.equal(numChatsInWindow(window), 1, "should be 1 chat open");
let chatDoc = chatbox.contentDocument;
let chatTitle = chatDoc.title;
let chatTitle = yield ContentTask.spawn(chatbox.content, null, function* () {
let chatDoc = content.document;
// Mutate the chat document a bit before we tear it off.
let div = chatDoc.createElement("div");
div.setAttribute("id", "testdiv");
div.setAttribute("test", "1");
chatDoc.body.appendChild(div);
return chatDoc.title;
});
Assert.equal(chatbox.getAttribute("label"), chatTitle,
"the new chatbox should show the title of the chat window");
// mutate the chat document a bit before we tear it off.
let div = chatDoc.createElement("div");
div.setAttribute("id", "testdiv");
div.setAttribute("test", "1");
chatDoc.body.appendChild(div);
// chatbox is open, lets detach. The new chat window will be caught in
// the window watcher below
let promise = promiseNewWindowLoaded();
@ -61,9 +64,11 @@ add_chat_task(function* testTearoffChat() {
chatbox = domwindow.document.getElementById("chatter")
Assert.equal(chatbox.getAttribute("label"), chatTitle, "window should have same title as chat");
div = chatbox.contentDocument.getElementById("testdiv");
Assert.equal(div.getAttribute("test"), "1", "docshell should have been swapped");
div.setAttribute("test", "2");
yield ContentTask.spawn(chatbox.content, null, function* () {
div = content.document.getElementById("testdiv");
is(div.getAttribute("test"), "1", "docshell should have been swapped");
div.setAttribute("test", "2");
});
// swap the window back to the chatbar
promise = promiseOneEvent(domwindow, "unload");
@ -77,8 +82,10 @@ add_chat_task(function* testTearoffChat() {
Assert.equal(chatbox.getAttribute("label"), chatTitle,
"the new chatbox should show the title of the chat window again");
div = chatbox.contentDocument.getElementById("testdiv");
Assert.equal(div.getAttribute("test"), "2", "docshell should have been swapped");
yield ContentTask.spawn(chatbox.content, null, function* () {
let div = content.document.getElementById("testdiv");
is(div.getAttribute("test"), "2", "docshell should have been swapped");
});
});
// Similar test but with 2 chats.

View File

@ -15,18 +15,12 @@ function promiseOpenChat(url, mode, focus, buttonSet = null) {
// we just through a few hoops to ensure the content document is fully
// loaded, otherwise tests that rely on that content may intermittently fail.
let callback = function(chatbox) {
if (chatbox.contentDocument.readyState == "complete") {
// already loaded.
let mm = chatbox.content.messageManager;
mm.sendAsyncMessage("WaitForDOMContentLoaded");
mm.addMessageListener("DOMContentLoaded", function cb() {
mm.removeMessageListener("DOMContentLoaded", cb);
deferred.resolve(chatbox);
return;
}
chatbox.addEventListener("load", function onload(event) {
if (event.target != chatbox.contentDocument || chatbox.contentDocument.location.href == "about:blank") {
return;
}
chatbox.removeEventListener("load", onload, true);
deferred.resolve(chatbox);
}, true);
});
}
let chatbox = Chat.open(null, {
origin: origin,
@ -68,6 +62,16 @@ function promiseOneEvent(target, eventName, capture) {
return deferred.promise;
}
function promiseOneMessage(target, messageName) {
return new Promise(resolve => {
let mm = target.messageManager;
mm.addMessageListener(messageName, function handler() {
mm.removeMessageListener(messageName, handler);
resolve();
});
});
}
// Return the number of chats in a browser window.
function numChatsInWindow(win) {
let chatbar = win.document.getElementById("pinnedchats");
@ -104,3 +108,31 @@ function add_chat_task(genFunction) {
}
});
}
function waitForCondition(condition, nextTest, errorMsg) {
var tries = 0;
var interval = setInterval(function() {
if (tries >= 100) {
ok(false, errorMsg);
moveOn();
}
var conditionPassed;
try {
conditionPassed = condition();
} catch (e) {
ok(false, e + "\n" + e.stack);
conditionPassed = false;
}
if (conditionPassed) {
moveOn();
}
tries++;
}, 100);
var moveOn = function() { clearInterval(interval); nextTest(); };
}
function promiseWaitForCondition(aConditionFn) {
return new Promise((resolve, reject) => {
waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
});
}

View File

@ -37,9 +37,11 @@ skip-if = true # bug 1115131
[browser_social_activation.js]
skip-if = e10s && debug # e10s/Linux/Debug Leaking docshells (bug 1150147)
[browser_social_chatwindow.js]
skip-if = true # Bug 1245798 'document-element-inserted' is not fired for chat windows anymore, so no mozSocial
[browser_social_chatwindow_resize.js]
skip-if = true # Bug 1245798 'document-element-inserted' is not fired for chat windows anymore, so no mozSocial
[browser_social_chatwindowfocus.js]
skip-if = e10s # tab crash on data url used in this test
skip-if = true # Bug 1245798 'document-element-inserted' is not fired for chat windows anymore, so no mozSocial
[browser_social_contextmenu.js]
skip-if = (os == 'linux' && e10s) # Bug 1072669 context menu relies on target element
[browser_social_errorPage.js]
@ -52,6 +54,7 @@ skip-if = (os == 'linux' && e10s) # Bug 1072669 context menu relies on target el
[browser_social_perwindowPB.js]
[browser_social_sidebar.js]
[browser_social_status.js]
skip-if = true # Bug 1245800 'onoffline' and 'ononline' not defined JS errors
[browser_social_window.js]
[browser_social_workercrash.js]
#skip-if = !crashreporter

View File

@ -122,6 +122,10 @@ var tests = {
},
testChatWindow: function(next) {
todo(false, "Bug 1245799 is needed to make error pages work again for chat windows.");
next();
return;
let panelCallbackCount = 0;
// chatwindow tests throw errors, which muddy test output, if the worker
// doesn't get test-init
@ -146,6 +150,10 @@ var tests = {
},
testChatWindowAfterTearOff: function(next) {
todo(false, "Bug 1245799 is needed to make error pages work again for chat windows.");
next();
return;
// Ensure that the error listener survives the chat window being detached.
let url = manifest.sidebarURL; /* empty html page */
let panelCallbackCount = 0;

View File

@ -497,12 +497,17 @@ function makeChat(mode, uniqueid, cb) {
}
// Note that we use promiseChatLoaded instead of the callback to ensure the
// content has started loading.
let chatbox = getChatBar().openChat(provider.origin, provider.name,
chatUrl + "?id=" + uniqueid, mode);
let chatbox = getChatBar().openChat({
origin: provider.origin,
title: provider.name,url: chatUrl + "?id=" + uniqueid,
mode: mode
});
chatbox.promiseChatLoaded.then(
() => {
info("chat window has opened");
chatbox.contentDocument.title = uniqueid;
chatbox.content.messageManager.sendAsyncMessage("Social:SetDocumentTitle", {
title: uniqueid
});
cb();
});
}