diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-15 00:47:17 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-15 00:47:17 +0000 |
commit | 5d4a8eb1c49b9a08ef4fd9f540a47e348307672f (patch) | |
tree | fd251326fdb8265b00fa2ded269973c2b1ce67a5 /chrome/browser/resources | |
parent | 12774990ee4f8f9c6bb2d9ccd032f9000a97b04a (diff) | |
download | chromium_src-5d4a8eb1c49b9a08ef4fd9f540a47e348307672f.zip chromium_src-5d4a8eb1c49b9a08ef4fd9f540a47e348307672f.tar.gz chromium_src-5d4a8eb1c49b9a08ef4fd9f540a47e348307672f.tar.bz2 |
Reworked extension to leverage magic iframes for speedy load times
and modified communication with chat engine for increased reliability.
Patch by seh@chromium.org:
http://codereview.chromium.org/2065004/show
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/2094007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47349 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources')
8 files changed, 324 insertions, 147 deletions
diff --git a/chrome/browser/resources/chat_manager/background.html b/chrome/browser/resources/chat_manager/background.html index 06a0c96..05b4b61 100644 --- a/chrome/browser/resources/chat_manager/background.html +++ b/chrome/browser/resources/chat_manager/background.html @@ -12,126 +12,139 @@ to route both incoming and outgoing chats through this central roster. --> <body> -<style> - .talk_roster { - position: fixed; - left: 0px; - top: 0px; - } - .talk_iframe { - width: 100%; - height: 100%; - border: none; - overflow-x: hidden; - overflow-y: hidden; - } -</style> -<script> - var args = { - 'host': 'talkgadget.google.com', - 'jsmode': 'pre', - 'hl': 'en', - }; - // Read args. - var urlParts = window.location.href.split(/[?&#]/); - for (var i = 1; i < urlParts.length; i++) { - var argParts = urlParts[i].split('='); - if (argParts.length == 2) { - args[argParts[0]] = argParts[1]; - } - } - document.write('<script src="https://' + args['host'] + - '/talkgadget/notifier-js?silent=true&host=https://' + args['host'] + - '/talkgadget/notifier-js' + - (args['jsmode'] != '' ? ('&jsmode=' + args['jsmode']) : '') + - '"></scr' + 'ipt>'); -</script> + <iframe + id='centralRoster' + src='central_roster.html'>Central Roster</iframe> <script src="js/chatbridgeeventtypes.js"></script> <script> - var chatClient = null; - if (window.GTalkNotifier) { - chatClient = new GTalkNotifier( - 'http://' + args['host'] + '/talkgadget/', - 'notifierclient' + - (args['jsmode'] != '' ? ('?jsmode=' + args['jsmode']) : ''), - 'ifpc_relay', - 'ifpc.js', - 'Google Talk', - { - hostCallback: function(){}, - xpcRelay: 'xpc_relay', - xpcBlank: 'xpc_blank', - locale: args['hl'], - isCentralRoster: true, - hideProfileCard: true + var centralRosterWindow; + var centralRosterJid; + var centralRosterPort; + var centralJidListenerPorts = []; + + // On loading central roster, reparent roster to viewer window. + function reparentCentralRosterToWindow() { + var backgroundDocument = centralRosterWindow.backgroundDocument; + if (backgroundDocument) { + var iframe = backgroundDocument.getElementById('centralRoster'); + if (iframe) { + var windowDocument = centralRosterWindow.document; + if (windowDocument) { + if (windowDocument.adoptNode) { + windowDocument.adoptNode(iframe); + } + windowDocument.body.appendChild(iframe); } - ); - } else { - document.write( - '<div class="talk_roster"><b>GTalkNotifier undefined</b></div>'); + } + } } - var centralRosterJid; - var tabIdToGmPort = {}; - // Notify all open Gmail pages of updated central roster jid. - function forwardCentralRosterJidToGmPorts() { - for (var tabId in tabIdToGmPort) { - var port = tabIdToGmPort[tabId]; - if (port != null) { - port.postMessage({jid: centralRosterJid}); + // On unloading central roster, reparent roster to background. + function reparentCenterRosterToBackground(event) { + var windowDocument = centralRosterWindow.document; + if (windowDocument) { + var iframe = windowDocument.getElementById('centralRoster'); + if (iframe) { + var backgroundDocument = centralRosterWindow.backgroundDocument; + if (backgroundDocument) { + if (backgroundDocument.adoptNode) { + backgroundDocument.adoptNode(iframe); + } + backgroundDocument.body.appendChild(iframe); + } } } + centralRosterWindow = null; } - // Observe all tab closures. Clear the corresponding Gmail tracking entry. - chrome.tabs.onRemoved.addListener(function(tabId) { - if (tabIdToGmPort[tabId] != null) { - delete tabIdToGmPort[tabId]; + // Open central roster or give it focus. + function openCentralRosterWindow() { + if (!centralRosterWindow) { + centralRosterWindow = window.open( + chrome.extension.getURL('central_roster_viewer.html'), + 'centralRosterWindow', + 'width=300,height=360,resizable=0,menubar=0,scrollbars=0'); + centralRosterWindow.backgroundDocument = document; + centralRosterWindow.onload = reparentCentralRosterToWindow; + centralRosterWindow.onbeforeunload = reparentCenterRosterToBackground; + } else { + centralRosterWindow.focus(); } - }); + } + + // Notify all port listeners of updated central roster jid. + function forwardCentralRosterJidToPortListeners() { + for (var listenerPort in centralJidListenerPorts) { + listenerPort.postMessage({jid: centralRosterJid}); + } + } + + // Central roster jid changed. Notify all listeners. + function centralJidUpdate(msg) { + if (centralRosterJid != msg.jid) { + centralRosterJid = msg.jid; + forwardCentralRosterJidToPortListeners(); + } + } - // Listen for content script connections with Gmail pages and add a - // corresponding tracking entry. + // Listen for content script connections. chrome.extension.onConnect.addListener(function(port) { - if (port.name == 'centralJidWatcher') { - tabIdToGmPort[port.sender.tab.id] = port; + // New central jid listener. + // Update with current central roster jid, and add to tracking array. + if (port.name == 'centralJidListener') { + port.postMessage({jid: centralRosterJid}); + centralJidListenerPorts.push(port); + + // Clear tracking array entry when content script closes. + port.onDisconnect.addListener(function(port) { + for (var index = 0; index < centralJidListenerPorts.length; ++index) { + var listenerPort = centralJidListenerPorts[index]; + if (listenerPort == port) { + centralJidListenerPorts.splice(index, 1); + break; + } + } + }); + // New central jid broadcaster. + // Add listener for jid changes, and track port for forwarding chats. + } else if (port.name == 'centralJidBroadcaster') { + if (centralRosterPort != port) { + if (centralRosterPort) { + centralRosterPort.onMessage.removeListener(centralJidUpdate); + } + centralRosterPort = port; + centralRosterPort.onMessage.addListener(centralJidUpdate); + + // Clear listener and central roster jid when content script closes + centralRosterPort.onDisconnect.addListener(function(port) { + if (centralRosterPort) { + centralRosterPort.onMessage.removeListener(centralJidUpdate); + centralRosterPort = null; + centralJidUpdate({jid: null}); + } + }); + } } }); // Listen for requests from our content scripts. chrome.extension.onRequest.addListener(function(request, sender) { switch (request.msg) { - // For new initiated chats, forward to this page's GTalk client. + // For new initiated chats, forward to the central roster port. case ChatBridgeEventTypes.SHOW_CHAT: - if (chatClient != null) { - chatClient._showChat(request.jid); - } - break; case ChatBridgeEventTypes.START_VIDEO: - if (chatClient != null) { - chatClient._startVideoChat(request.jid); - } - break; case ChatBridgeEventTypes.START_VOICE: - if (chatClient != null) { - chatClient._startVoiceChat(request.jid); - } - break; - // For changes in the central roster, forward to all Gmail pages. - case ChatBridgeEventTypes.CENTRAL_USER_UPDATE: - if (centralRosterJid != request.jid) { - centralRosterJid = request.jid; - forwardCentralRosterJidToGmPorts(); + if (centralRosterPort) { + centralRosterPort.postMessage( + {chatType: request.msg, jid: request.jid}); + } else { + // We should not have been forwarded this message. Make sure our + // listeners are updated with the current central roster jid. + forwardCentralRosterJidToPortListeners(); } break; - // For a request of the latest central roster jid, respond back to the - // requesting port. - case ChatBridgeEventTypes.REQUEST_CENTRAL_USER: - var tabId = sender.tab.id; - var port = tabIdToGmPort[tabId]; - if (port != null) { - port.postMessage({jid: centralRosterJid}); - } + case ChatBridgeEventTypes.OPEN_CENTRAL_ROSTER: + openCentralRosterWindow(); break; } }); diff --git a/chrome/browser/resources/chat_manager/central_roster.html b/chrome/browser/resources/chat_manager/central_roster.html new file mode 100644 index 0000000..41df51e --- /dev/null +++ b/chrome/browser/resources/chat_manager/central_roster.html @@ -0,0 +1,75 @@ +<!DOCTYPE html> +<html> +<!-- + +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. + +Central roster: hosting all Google Talk chats in ChromeOS. + +--> +<body> +<style> + .talk_roster { + position: fixed; + left: 0px; + top: 0px; + } + .talk_iframe { + width: 100%; + height: 100%; + border: none; + overflow-x: hidden; + overflow-y: hidden; + } +</style> +<script> + var args = { + 'protocol': 'https', + 'host': 'talkgadget.google.com', + 'jsmode': 'pre', + 'hl': 'en', + }; + // Read args. + var urlParts = window.location.href.split(/[?&#]/); + for (var i = 1; i < urlParts.length; i++) { + var argParts = urlParts[i].split('='); + if (argParts.length == 2) { + args[argParts[0]] = argParts[1]; + } + } + document.write('<script src="' + + args['protocol'] + '://' + args['host'] + + '/talkgadget/notifier-js?silent=true&host=' + + args['protocol'] + '://' + args['host'] + + '/talkgadget/notifier-js' + + (args['jsmode'] != '' ? ('&jsmode=' + args['jsmode']) : '') + + '"></scr' + 'ipt>'); +</script> +<script> + var chatClient = null; + if (window.GTalkNotifier) { + chatClient = new GTalkNotifier( + args['protocol'] + '://' + args['host'] + '/talkgadget/', + 'notifierclient' + + (args['jsmode'] != '' ? ('?jsmode=' + args['jsmode']) : ''), + 'ifpc_relay', + 'ifpc.js', + 'Google Talk', + { + hostCallback: function(){}, + xpcRelay: 'xpc_relay', + xpcBlank: 'xpc_blank', + locale: args['hl'], + isCentralRoster: true, + hideProfileCard: true + } + ); + } else { + document.write( + '<div class="talk_roster"><b>GTalkNotifier undefined</b></div>'); + } +</script> +</body> +</html> diff --git a/chrome/browser/resources/chat_manager/central_roster_viewer.html b/chrome/browser/resources/chat_manager/central_roster_viewer.html new file mode 100644 index 0000000..2f18b7b --- /dev/null +++ b/chrome/browser/resources/chat_manager/central_roster_viewer.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<!-- + +Copyright (c) 2010 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. + +--> + <head> + <title>Online friends</title> + <!-- Set height to 98% to get around bug in css calculation that triggers + a vertical scroll bar. --> + <style> + iframe { + border: 0px; + margin: 0px; + padding: 0px; + width: 100%; + height: 98%; + } + </style> + </head> + <body topmargin='0' leftmargin='0'> + <!-- Place for central roster --> + </body> +</html> diff --git a/chrome/browser/resources/chat_manager/js/centralrosterhook.js b/chrome/browser/resources/chat_manager/js/centralrosterhook.js new file mode 100644 index 0000000..d9c70e7 --- /dev/null +++ b/chrome/browser/resources/chat_manager/js/centralrosterhook.js @@ -0,0 +1,12 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Search for communication channel div. +var divOpenerHandler = document.getElementById('central_roster_opener'); +if (divOpenerHandler) { + divOpenerHandler.addEventListener(ChatBridgeEventTypes.OPEN_CENTRAL_ROSTER, + function(event) { + chrome.extension.sendRequest({msg: 'openCentralRoster'}); + }, false); +} diff --git a/chrome/browser/resources/chat_manager/js/chatbridgeeventtypes.js b/chrome/browser/resources/chat_manager/js/chatbridgeeventtypes.js index e2d6223..7563917 100644 --- a/chrome/browser/resources/chat_manager/js/chatbridgeeventtypes.js +++ b/chrome/browser/resources/chat_manager/js/chatbridgeeventtypes.js @@ -10,6 +10,8 @@ var ChatBridgeEventTypes = { SHOW_CHAT: 'showChat', START_VIDEO: 'startVideo', START_VOICE: 'startVoice', + CENTRAL_USER_SET: 'centralJidSet', CENTRAL_USER_UPDATE: 'centralJidUpdate', - REQUEST_CENTRAL_USER: 'getCentralJid' + CENTRAL_USER_WATCHER: 'getCentralJid', + OPEN_CENTRAL_ROSTER: 'openCentralRoster' }; diff --git a/chrome/browser/resources/chat_manager/js/chatbridgehook.js b/chrome/browser/resources/chat_manager/js/chatbridgehook.js index 5e3854c..aae422f 100644 --- a/chrome/browser/resources/chat_manager/js/chatbridgehook.js +++ b/chrome/browser/resources/chat_manager/js/chatbridgehook.js @@ -2,23 +2,63 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Port used for: +// 1. forwarding updated central user from the chat page to the background. +// 2. forwarding chats from the background to the chat page we're attached to. +var centralJidBroadcasterPort; + +// Port used for: +// 1. forwarding central user requests from the chat page to the background. +// 2. forwarding the central user from the background to the chat page. +var centralJidListenerChatPort; + +// The chat page div used to funnel events through. +var divRosterHandler; + /** - * Central user update listener triggered by a change in Chrome chat code. - * @param {MessageEvent} event the user update event. + * Manage two-way communication with the central roster. Updated jid's are + * forwarded to the background, while chats are forwarded to the page. + * @param {MessageEvent} event the new central roster jid event. */ -function centralUserUpdate(event) { +function centralRosterHandler(event) { + if (!centralJidBroadcasterPort) { + centralJidBroadcasterPort = chrome.extension.connect( + {name: 'centralJidBroadcaster'}); + centralJidBroadcasterPort.onMessage.addListener(function(msg) { + var chatJid = msg.jid; + var showChatEvent = document.createEvent('MessageEvent'); + showChatEvent.initMessageEvent(msg.chatType, true, true, chatJid); + divRosterHandler.dispatchEvent(showChatEvent); + }); + } var centralRosterJid = event.data; - chrome.extension.sendRequest( - { - msg: ChatBridgeEventTypes.CENTRAL_USER_UPDATE, - jid: centralRosterJid - } - ); + centralJidBroadcasterPort.postMessage({jid: centralRosterJid}); +} + +/** + * Setup central roster jid listener. + * @param {MessageEvent} event the event. + */ +function setupCentralRosterJidListener(event) { + if (!centralJidListenerChatPort) { + centralJidListenerChatPort = chrome.extension.connect( + {name: 'centralJidListener'}); + centralJidListenerChatPort.onMessage.addListener(function(msg) { + var centralRosterJid = msg.jid; + var outgoingChatEvent = document.createEvent('MessageEvent'); + outgoingChatEvent.initMessageEvent( + ChatBridgeEventTypes.CENTRAL_USER_UPDATE, + true, true, centralRosterJid); + divRosterHandler.dispatchEvent(outgoingChatEvent); + }); + } } // Search for communication channel div. -var divRosterHandler = document.getElementById('roster_comm_link'); +divRosterHandler = document.getElementById('roster_comm_link'); if (divRosterHandler) { - divRosterHandler.addEventListener(ChatBridgeEventTypes.CENTRAL_USER_UPDATE, - centralUserUpdate, false); + divRosterHandler.addEventListener(ChatBridgeEventTypes.CENTRAL_USER_SET, + centralRosterHandler, false); + divRosterHandler.addEventListener(ChatBridgeEventTypes.CENTRAL_USER_WATCHER, + setupCentralRosterJidListener, false); } diff --git a/chrome/browser/resources/chat_manager/js/gmailbridgehook.js b/chrome/browser/resources/chat_manager/js/gmailbridgehook.js index c1c4583..54b9b2f 100644 --- a/chrome/browser/resources/chat_manager/js/gmailbridgehook.js +++ b/chrome/browser/resources/chat_manager/js/gmailbridgehook.js @@ -2,6 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Port used for: +// 1. forwarding central user requests from the gmail page to the background. +// 2. forwarding the central user from the background to the gmail page. +var centralJidListenerGmailPort; + +// The gmail page div used to funnel events through. +var divGmailHandler; + /** * Triggered on a user initiated chat request. Forward to extension to be * processed by the Chrome central roster. @@ -13,42 +21,33 @@ function forwardChatEvent(event) { } /** - * Triggered by Gmail on startup to request the current central roster jid. - * @param {MessageEvent} event the central roster jid request event. + * Setup central roster jid listener. + * @param {MessageEvent} event the event. */ -function requestCentralUserJid(event) { - chrome.extension.sendRequest( - {msg: ChatBridgeEventTypes.REQUEST_CENTRAL_USER}); +function setupCentralRosterJidListener(event) { + if (!centralJidListenerGmailPort) { + centralJidListenerGmailPort = chrome.extension.connect( + {name: 'centralJidListener'}); + centralJidListenerGmailPort.onMessage.addListener(function(msg) { + var centralRosterJid = msg.jid; + var outgoingChatEvent = document.createEvent('MessageEvent'); + outgoingChatEvent.initMessageEvent( + ChatBridgeEventTypes.CENTRAL_USER_UPDATE, + true, true, centralRosterJid); + divGmailHandler.dispatchEvent(outgoingChatEvent); + }); + } } -/** - * Initialize a communication channel with a Gmail chat component and the - * Chrome extension background logic. - * @param {HTMLElement} divHandler the div element used to communicate. - */ -function attachToDivGmHandler(divHandler) { - divHandler.addEventListener(ChatBridgeEventTypes.SHOW_CHAT, +// Search for communication channel div. +divGmailHandler = document.getElementById('mainElement'); +if (divGmailHandler) { + divGmailHandler.addEventListener(ChatBridgeEventTypes.SHOW_CHAT, forwardChatEvent, false); - divHandler.addEventListener(ChatBridgeEventTypes.START_VIDEO, + divGmailHandler.addEventListener(ChatBridgeEventTypes.START_VIDEO, forwardChatEvent, false); - divHandler.addEventListener(ChatBridgeEventTypes.START_VOICE, + divGmailHandler.addEventListener(ChatBridgeEventTypes.START_VOICE, forwardChatEvent, false); - divHandler.addEventListener(ChatBridgeEventTypes.REQUEST_CENTRAL_USER, - requestCentralUserJid, false); - // Set up a direct channel with the extension to forward updated central - // roster jid's. - var port = chrome.extension.connect({name: 'centralJidWatcher'}); - port.onMessage.addListener(function(msg) { - var centralRosterJid = msg.jid; - var outgoingChatEvent = document.createEvent('MessageEvent'); - outgoingChatEvent.initMessageEvent( - ChatBridgeEventTypes.CENTRAL_USER_UPDATE, true, true, centralRosterJid); - divHandler.dispatchEvent(outgoingChatEvent); - }); -} - -// Search for communication channel div. -var divGmailHandler = document.getElementById('mainElement'); -if (divGmailHandler) { - attachToDivGmHandler(divGmailHandler); + divGmailHandler.addEventListener(ChatBridgeEventTypes.CENTRAL_USER_WATCHER, + setupCentralRosterJidListener, false); } diff --git a/chrome/browser/resources/chat_manager/manifest.json b/chrome/browser/resources/chat_manager/manifest.json index 9d55ad4..baa6ddc 100644 --- a/chrome/browser/resources/chat_manager/manifest.json +++ b/chrome/browser/resources/chat_manager/manifest.json @@ -1,8 +1,8 @@ { "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDrlwvcbUtVrbQvI7EPV1BTa63N8YkbBToHzxlMl0IzSBwOV+TUOsHE8vRq0HZWuwMAGeH8WdWVC3HRNdES8lScjlzxb1TsTQJAsF+hLXgcjgCUSSSGCfFzypvuvKsRQTx0d02yfWKJa47o0Ws5wL72NVtc7c51HujwWYg+Mz01wIDAQAB", - "name": "Gmail to Chrome chat bridge (by Google)", + "name": "Chrome chat manager (by Google)", "version": "1.0", - "description": "Gmail to Chrome chat bridge", + "description": "Chrome chat manager", "background_page": "background.html", "content_scripts": [ { "js": [ @@ -25,12 +25,21 @@ "https://mail.google.com/*" ], "run_at": "document_end" + }, { + "js": [ + "js/chatbridgeeventtypes.js", + "js/centralrosterhook.js" + ], + "matches": [ + "file:///*/*", + "http://*/*", + "https://*/*" + ], + "run_at": "document_end" }], "permissions": [ "tabs", "http://talkgadget.google.com/*", - "https://talkgadget.google.com/*", - "http://mail.google.com/*", - "https://mail.google.com/*" + "https://talkgadget.google.com/*" ] } |