Bug 807997 - allow chats to open in any suitable top-level window. r=gavin

This commit is contained in:
Mark Hammond 2012-12-07 10:56:17 +11:00
Родитель 6a72436e40
Коммит c76347ad1f
4 изменённых файлов: 90 добавлений и 5 удалений

Просмотреть файл

@ -250,10 +250,13 @@ let SocialChatBar = {
if (!SocialUI.haveLoggedInUser())
return false;
let docElem = document.documentElement;
let chromeless = docElem.getAttribute("disablechrome") ||
docElem.getAttribute("chromehidden").indexOf("extrachrome") >= 0;
let chromeless = docElem.getAttribute("chromehidden").indexOf("extrachrome") >= 0;
return Social.uiVisible && !chromeless;
},
// Does this chatbar have any chats (whether minimized, collapsed or normal)
get hasChats() {
return !!this.chatbar.firstElementChild;
},
openChat: function(aProvider, aURL, aCallback, aMode) {
if (this.isAvailable)
this.chatbar.openChat(aProvider, aURL, aCallback, aMode);

Просмотреть файл

@ -434,6 +434,50 @@ var tests = {
port.postMessage({topic: "test-init"});
},
testChatWindowChooser: function(next) {
// Tests that when a worker creates a chat, it is opened in the correct
// window.
const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
let chatId = 1;
let port = Social.provider.getWorkerPort();
port.postMessage({topic: "test-init"});
function openChat(callback) {
port.onmessage = function(e) {
if (e.data.topic == "got-chatbox-message")
callback();
}
let url = chatUrl + "?" + (chatId++);
port.postMessage({topic: "test-worker-chat", data: url});
}
// open a chat (it will open in the main window)
ok(!window.SocialChatBar.hasChats, "first window should start with no chats");
openChat(function() {
ok(window.SocialChatBar.hasChats, "first window has the chat");
// create a second window - although this will be the "most recent",
// the fact the first window has a chat open means the first will be targetted.
let secondWindow = OpenBrowserWindow();
secondWindow.addEventListener("load", function loadListener() {
secondWindow.removeEventListener("load", loadListener);
ok(!secondWindow.SocialChatBar.hasChats, "second window has no chats");
openChat(function() {
ok(!secondWindow.SocialChatBar.hasChats, "second window still has no chats");
is(window.SocialChatBar.chatbar.childElementCount, 2, "first window now has 2 chats");
window.SocialChatBar.chatbar.removeAll();
// now open another chat - it should open in the second window (as
// it is the "most recent" and no other windows have chats)
openChat(function() {
ok(!window.SocialChatBar.hasChats, "first window has no chats");
ok(secondWindow.SocialChatBar.hasChats, "second window has a chat");
secondWindow.close();
next();
});
});
})
});
},
// XXX - note this must be the last test until we restore the login state
// between tests...
testCloseOnLogout: function(next) {

Просмотреть файл

@ -249,12 +249,51 @@ function ensureProviderOrigin(provider, url) {
return fullURL;
}
function isWindowGoodForChats(win) {
return win.SocialChatBar && win.SocialChatBar.isAvailable;
}
function findChromeWindowForChats(preferredWindow) {
if (preferredWindow && isWindowGoodForChats(preferredWindow))
return preferredWindow;
// no good - so let's go hunting. We are now looking for a navigator:browser
// window that is suitable and already has chats open, or failing that,
// any suitable navigator:browser window.
let first, best, enumerator;
// *sigh* - getZOrderDOMWindowEnumerator is broken everywhere other than
// Windows. We use BROKEN_WM_Z_ORDER as that is what the c++ code uses
// and a few bugs recommend searching mxr for this symbol to identify the
// workarounds - we want this code to be hit in such searches.
const BROKEN_WM_Z_ORDER = Services.appinfo.OS != "WINNT";
if (BROKEN_WM_Z_ORDER) {
// this is oldest to newest and no way to change the order.
enumerator = Services.wm.getEnumerator("navigator:browser");
} else {
// here we explicitly ask for bottom-to-top so we can use the same logic
// where BROKEN_WM_Z_ORDER is true.
enumerator = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", false);
}
while (enumerator.hasMoreElements()) {
let win = enumerator.getNext();
if (win && isWindowGoodForChats(win)) {
first = win;
if (win.SocialChatBar.hasChats)
best = win;
}
}
return best || first;
}
this.openChatWindow =
function openChatWindow(chromeWindow, provider, url, callback, mode) {
if (!chromeWindow.SocialChatBar)
chromeWindow = findChromeWindowForChats(chromeWindow);
if (!chromeWindow)
return;
let fullURL = ensureProviderOrigin(provider, url);
if (!fullURL)
return;
chromeWindow.SocialChatBar.openChat(provider, fullURL, callback, mode);
// getAttention is ignored if the target window is already foreground, so
// we can call it unconditionally.
chromeWindow.getAttention();
}

Просмотреть файл

@ -80,8 +80,7 @@ WorkerAPI.prototype = {
data: results});
},
'social.request-chat': function(data) {
let xulWindow = Services.wm.getMostRecentWindow("navigator:browser").getTopWin();
openChatWindow(xulWindow, this._provider, data, null, "minimized");
openChatWindow(null, this._provider, data, null, "minimized");
},
'social.notification-create': function(data) {
if (!Services.prefs.getBoolPref("social.toast-notifications.enabled"))