// 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(); } }