// Firefox extension enabling the use of Gmail chat across multiple tabs.
// Copyright (C) 2007 Jack Wootton .
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
var GmailExtensionChat =
{
_chatMediators : [],
_tabMediators : [],
onMenuItemCommandApply : function(aEventObject)
{
GmailExtensionChat.initialize();
if ( GmailExtensionChat.isInitialized() )
GmailExtensionChat.applyGmailChats(gBrowser.selectedBrowser);
},
onMenuItemCommandApplyAll : function(aEventObject)
{
GmailExtensionChat.initialize();
if ( GmailExtensionChat.isInitialized() )
GmailExtensionChat.applyAllGmailChats(gBrowser.selectedBrowser);
},
onMenuItemCommandRemove : function(aEventObject)
{
GmailExtensionChat.initialize();
if ( GmailExtensionChat.isInitialized() )
GmailExtensionChat.removeGmailChats(gBrowser.selectedBrowser);
},
onMenuItemCommandRemoveAll : function(aEventObject)
{
GmailExtensionChat.initialize();
if ( GmailExtensionChat.isInitialized() )
GmailExtensionChat.removeAllGmailChats();
},
onMenuItemCommandClose : function(aEventObject)
{
GmailExtensionChat.expunge();
},
initialize : function()
{
var initialized = GmailExtensionChat.isInitialized();
if (! initialized)
{
var gmailTab = null;
try
{
gmailTab = GmailExtensionChat.extractGMailTab();
}
catch (exception)
{
ConsoleService.logSimple("Error extracting Gmail tab.");
return;
}
var gmailFrame = null;
try
{
gmailFrame = GmailExtensionChat.extractGMailFrame( gmailTab );
}
catch (exception)
{
ConsoleService.logSimple("Error extracting Gmail frame.");
return;
}
try
{
GmailExtensionChat.extractGmailChats( gmailFrame );
}
catch (exception)
{
ConsoleService.logSimple("Error extracting Gmail chats.");
return;
}
try
{
SurrogateElements.createElements( gmailFrame.contentWindow.document );
}
catch (exception)
{
ConsoleService.logSimple("Error creating template elements.");
return;
}
try
{
UserStylesheetService.loadRemoteChatStylesheet();
}
catch (exception)
{
ConsoleService.logSimple("Error loading Stylesheet Service.");
return;
}
}
},
isInitialized : function()
{
if (GmailExtensionChat._chatMediators != null)
{
return (GmailExtensionChat._chatMediators.length > 0) &&
(GmailExtensionChat._gmailDocument != null) &&
(UserStylesheetService.isLoaded());
}
return false;
},
extractGMailTab : function()
{
if (gBrowser != null)
{
var tabCount = gBrowser.browsers.length;
for (var i = 0; i < tabCount; i++)
{
var xulTab = gBrowser.getBrowserAtIndex(i);
try
{
var containsGmailUrl = (xulTab.currentURI.spec).
indexOf(Utility.GMAIL_CHAT_SERVER) > -1;
if (containsGmailUrl)
return xulTab;
}
catch(exception)
{
// Try next tab.
}
}
}
// Should never get here.
throw Exceptions.EXTERNAL_ERROR;
},
extractGMailFrame : function(aXulTab)
{
ConsoleService.logSimple("extractGMailFrame");
if (aXulTab == null)
throw Exceptions.EXTERNAL_ERROR;
ConsoleService.logSimple("1");
var gmailContentWindow = aXulTab.contentWindow;
if (gmailContentWindow == null)
throw Exceptions.EXTERNAL_ERROR;
ConsoleService.logSimple("2");
var gmailDocument = gmailContentWindow.document;
if (gmailDocument == null)
throw Exceptions.EXTERNAL_ERROR;
ConsoleService.logSimple("3");
if (! this._document.getElementsByTagName)
throw Exceptions.EXTERNAL_ERROR;
ConsoleService.logSimple("4");
var gmailFrames = gmailDocument.getElementsByTagName(Tags.FRAME);
var isMainFrame = false;
for (var i = 0; i < gmailFrames.length; i++)
{
if (gmailFrames[i].hasAttribute("name"))
{
isMainFrame = gmailFrames[i].getAttribute("name") ==
Utility.GMAIL_DOCUMENT_NAME;
if (isMainFrame)
return gmailFrames[i];
}
}
// Should never get here.
throw Exceptions.EXTERNAL_ERROR;
},
extractGmailChats : function(aXhtmlFrame)
{
if (aXhtmlFrame == null)
throw Exceptions.EXTERNAL_ERROR;
var potentialElementId = "";
var tmpIframe = null;
// Count from 1 because frame id ol0 not used for chats.
for (var i = 1; i <= Utility.MAX_GMAIL_CHAT_FRAMES; i++)
{
potentialElementId = "ol" + i;
tmpIframe = null;
tmpIframe = aXhtmlFrame.getElementById( potentialElementId );
if (tmpIframe != null)
{
try
{
GmailExtensionChat.populateGmailChat( tmpIframe );
}
catch (exception)
{
throw Exceptions.EXTERNAL_ERROR;
}
}
}
},
populateGmailChat : function(aXhtmlIframe)
{
if (aXhtmlIframe == null)
throw Exceptions.EXTERNAL_ERROR;
var chatMediator = new ChatMediator();
var gmailChat = new GmailChat( chatMediator );
chatMediator.setGmailChat( gmailChat );
try
{
gmailChat.initialize( aXhtmlIframe );
}
catch (exception)
{
throw Exceptions.EXTERNAL_ERROR;
}
// Everything is OK, so add ChatMediator
var i = GmailExtensionChat._chatMediators.length;
GmailExtensionChat._chatMediators[i] = chatMediator;
},
applyGmailChats : function(aXulTab)
{
var tabMediator = null;
try
{
tabMediator = GmailExtensionChat.generateTabMediator(aXulTab);
}
catch (exception)
{
ConsoleService.logSimple("Error generating TabMediator");
return;
}
try
{
GmailExtensionChat.generateRemoteChats(tabMediator);
}
catch (exception)
{
ConsoleService.logSimple("Error generating RemoteChats.");
return;
}
},
applyAllGmailChats : function()
{
var numOfTabs = gBrowser.browsers.length;
for (var i = 0; i < numOfTabs; i++)
{
var xulTab = gBrowser.getBrowserAtIndex(i);
try
{
var containsGmailUrl = (xulTab.currentURI.spec).
indexOf(Utility.GMAIL_CHAT_SERVER) > -1;
if (! containsGmailUrl)
GmailExtensionChat.applyGmailChats(xulTab);
}
catch(exception)
{
// Try next tab.
}
}
},
removeGmailChats : function(aXulTab)
{
var cachedTabMediator = GmailExtensionChat.
getTabMediatorFromXulTab(aXulTab);
if (cachedTabMediator == null)
{
ConsoleService.logSimple("Error obtaining TabMediator.");
return;
}
else
{
tabMediator.removeAssociatedRemoteChats();
var index = GmailExtensionChat._tabMediators.indexOf(tabMediator);
var tabMediatorArray = this._tabMediators.splice(index,1);
for (var i = 0; i < tabMediatorArray.length; i++)
{
try
{
tabMediatorArray[i].expunge();
}
catch (exception)
{
ConsoleService.logSimple("Called expunge on populated object.");
}
tabMediatorArray[i] = null;
}
}
},
removeAllGmailChats : function()
{
var tabMediatorArray = [];
while (GmailExtensionChat._tabMediators.length > 0)
{
GmailExtensionChat._tabMediators[i].removeAssociatedChats();
tabMediatorArray = this._tabMediators.splice(
this._tabMediators.length-1, 1);
for (var k = 0; k < tabMediatorArray.length; k++)
{
try
{
tabMediatorArray[k].expunge();
}
catch (exception)
{
ConsoleService.logSimple("Called expunge on populated object.");
}
tabMediatorArray[k] = null;
}
}
},
generateTabMediator : function(aXulTab)
{
var cachedTabMediator = GmailExtensionChat.
getTabMediatorFromXulTab(aXulTab);
var tabMediator = null;
if (cachedTabMediator == null)
{
tabMediator = new TabMediator();
var tab = new Tab(tabMediator);
try
{
tab.initialize(aXulTab);
}
catch (exception)
{
throw Exceptions.INTERNAL_ERROR;
}
tabMediator.setTab(tab);
this._tabMediators[this._tabMediators.length] = tabMediator;
}
else
{
tabMediator = cachedTabMediator;
}
return tabMediator;
},
getTabMediatorFromXulTab : function(aXulTab)
{
var tabExists = false;
for (var i = 0; i < this._tabMediators.length; i++)
{
tabExists = this._tabMediators[i].isTabRegistered(aXulTab);
if (tabExists)
return this._tabMediators[i];
}
return null;
},
generateRemoteChats : function(aTabMediator)
{
// Does TabMediator contain a RemoteChat
// that already displays the chat contained in ChatMediator?
for (var i = 0; i < this._chatMediators.length; i++)
{
var chatMediator = this._chatMediators[i];
if (chatMediator.isActive())
{
var chatDisplayed = aTabMediator.alreadyDisplaysChat(chatMediator);
if (! chatDisplayed)
{
// Create RemoteChat that links a ChatMediator and TabMediator.
var remoteChat = new RemoteChat(chatMediator, aTabMediator);
chatMediator.addRemoteChat(remoteChat);
aTabMediator.addRemoteChat(remoteChat);
// Build gui, register listeners, populate with conversation.
try
{
remoteChat.initialize();
}
catch (exception)
{
aChatMediator.removeRemoteChat(remoteChat);
aTabMediator.removeRemoteChat(remoteChat);
ConsoleService.logSimple("Error initializing RemoteChat.");
}
}
}
}
},
notifyNewChatSession : function(aChatMediator)
{
var chatDisplayed = false;
for (var i = 0; i < this._tabMediators.length; i++)
{
chatDisplayed = this._tabMediators[i].alreadyDisplaysChat(aChatMediator);
if (! chatDisplayed)
{
var remoteChat = new RemoteChat(aChatMediator, tabMediator[i]);
aChatMediator.addRemoteChat(remoteChat);
tabMediator[i].addRemoteChat(remoteChat);
// Build gui, register listeners, populate with conversation.
try
{
remoteChat.initialize();
}
catch (exception)
{
aChatMediator.removeRemoteChat(remoteChat);
tabMediator[i].removeRemoteChat(remoteChat);
ConsoleService.logSimple("Error initializing RemoteChat.");
}
}
}
},
notifyEndChatSession : function(aChatMediator)
{
aChatMediator.removeAssociatedRemoteChats();
},
attachTabClosedListener : function()
{
if (gBrowser.tabContainer != null)
{
var container = gBrowser.tabContainer;
container.addEventListener("TabClose",
GmailExtensionChat.onTabClose,
false);
}
},
removeTabClosedListener : function()
{
var container = gBrowser.tabContainer;
container.removeEventListener("TabClose",
GmailExtensionChat.onTabClose,
false);
},
onTabClose : function(aEventObject)
{
var closedXulTab = aEventObject.target.linkedBrowser;
GmailExtensionChat.removeGmailChats(closedXulTab);
},
expunge : function()
{
GmailExtensionChat.removeAllGmailChats();
// Now _tabMediators should be [].
// RemoteChats cleared from both ChatMediator and TabMediator
var chatMediatorArray = [];
while (GmailExtensionChat._chatMediators.length > 0)
{
chatMediatorArray = this._chatMediators.splice(
this._chatMediators.length-1, 1);
for (var k = 0; k < chatMediatorArray.length; k++)
{
try
{
chatMediatorArray[k].expunge();
}
catch (exception)
{
ConsoleService.logSimple("Called expunge on populated object.");
}
chatMediatorArray[k] = null;
}
}
// Now _chatMediators should be [].
GmailExtensionChat._gmailDocument = null;
// Now _gmailDocument should be null.
UserStylesheetService.unLoadRemoteChatStylesheet();
}
}