Index: remoting/webapp/app_remoting/js/app_connected_view.js |
diff --git a/remoting/webapp/app_remoting/js/app_connected_view.js b/remoting/webapp/app_remoting/js/app_connected_view.js |
index 719681a36a498f397c7322345cb142f429c3c0ad..e39d445e35d1e51219024524f057a5f59ca07f6c 100644 |
--- a/remoting/webapp/app_remoting/js/app_connected_view.js |
+++ b/remoting/webapp/app_remoting/js/app_connected_view.js |
@@ -15,20 +15,50 @@ var remoting = remoting || {}; |
'use strict'; |
/** |
+ * Interval to test the connection speed. |
+ * @const {number} |
+ */ |
+var CONNECTION_SPEED_PING_INTERVAL_MS = 10 * 1000; |
+ |
+/** |
+ * Interval to refresh the google drive access token. |
+ * @const {number} |
+ */ |
+var DRIVE_ACCESS_TOKEN_REFRESH_INTERVAL_MS = 15 * 60 * 1000; |
+ |
+/** |
* @param {HTMLElement} containerElement |
* @param {remoting.ConnectionInfo} connectionInfo |
* |
* @constructor |
* @implements {base.Disposable} |
+ * @implements {remoting.ProtocolExtension} |
*/ |
remoting.AppConnectedView = function(containerElement, connectionInfo) { |
- |
/** @private */ |
this.plugin_ = connectionInfo.plugin(); |
/** @private */ |
this.host_ = connectionInfo.host(); |
+ /** @private {remoting.ContextMenuAdapter} */ |
+ var menuAdapter = new remoting.ContextMenuChrome(); |
+ |
+ // Initialize the context menus. |
+ if (!remoting.platformIsChromeOS()) { |
+ menuAdapter = |
+ new remoting.ContextMenuDom(document.getElementById('context-menu')); |
+ } |
+ |
+ this.contextMenu_ = new remoting.ApplicationContextMenu(menuAdapter); |
+ this.contextMenu_.setHostId(connectionInfo.host().hostId); |
+ |
+ /** @private */ |
+ this.keyboardLayoutsMenu_ = new remoting.KeyboardLayoutsMenu(menuAdapter); |
+ |
+ /** @private */ |
+ this.windowActivationMenu_ = new remoting.WindowActivationMenu(menuAdapter); |
+ |
var baseView = new remoting.ConnectedView( |
this.plugin_, containerElement, |
containerElement.querySelector('.mouse-cursor-overlay')); |
@@ -47,13 +77,20 @@ remoting.AppConnectedView = function(containerElement, connectionInfo) { |
this.disposables_ = new base.Disposables( |
baseView, windowShapeHook, desktopSizeHook); |
+ /** @private */ |
+ this.supportsGoogleDrive_ = connectionInfo.session().hasCapability( |
+ remoting.ClientSession.Capability.GOOGLE_DRIVE); |
+ |
this.resizeHostToClientArea_(); |
+ this.plugin_.extensions().register(this); |
}; |
/** |
* @return {void} Nothing. |
*/ |
remoting.AppConnectedView.prototype.dispose = function() { |
+ this.windowActivationMenu_.setExtensionMessageSender(base.doNothing); |
+ this.keyboardLayoutsMenu_.setExtensionMessageSender(base.doNothing); |
base.dispose(this.disposables_); |
}; |
@@ -93,4 +130,118 @@ remoting.AppConnectedView.prototype.onDesktopSizeChanged_ = |
this.plugin_.element().style.height = newSize.height + 'px'; |
}; |
+/** |
+ * @return {Array<string>} |
+ * @override {remoting.ProtocolExtension} |
+ */ |
+remoting.AppConnectedView.prototype.getExtensionTypes = function() { |
+ return ['openURL', 'onWindowRemoved', 'onWindowAdded', |
+ 'onAllWindowsMinimized', 'setKeyboardLayouts', 'pingResponse']; |
+}; |
+ |
+/** |
+ * @param {function(string,string)} sendMessageToHost Callback to send a message |
+ * to the host. |
+ * @override {remoting.ProtocolExtension} |
+ */ |
+remoting.AppConnectedView.prototype.startExtension = function( |
+ sendMessageToHost) { |
+ this.windowActivationMenu_.setExtensionMessageSender(sendMessageToHost); |
+ this.keyboardLayoutsMenu_.setExtensionMessageSender(sendMessageToHost); |
+ |
+ remoting.identity.getUserInfo().then(function(userInfo) { |
+ sendMessageToHost('setUserDisplayInfo', |
+ JSON.stringify({fullName: userInfo.name})); |
+ }); |
+ |
+ var onRestoreHook = new base.ChromeEventHook( |
+ chrome.app.window.current().onRestored, function() { |
+ sendMessageToHost('restoreAllWindows', ''); |
+ }); |
+ |
+ var pingTimer = new base.RepeatingTimer(function() { |
+ var message = {timestamp: new Date().getTime()}; |
+ sendMessageToHost('pingRequest', JSON.stringify(message)); |
+ }, CONNECTION_SPEED_PING_INTERVAL_MS); |
+ |
+ this.disposables_.add(onRestoreHook, pingTimer); |
+ |
+ if (this.supportsGoogleDrive_) { |
+ this.disposables_.add(new base.RepeatingTimer( |
+ this.sendGoogleDriveAccessToken_.bind(this, sendMessageToHost), |
+ DRIVE_ACCESS_TOKEN_REFRESH_INTERVAL_MS, true)); |
+ } |
+}; |
+ |
+/** |
+ * @param {string} type The message type. |
+ * @param {Object} message The parsed extension message data. |
+ * @override {remoting.ProtocolExtension} |
+ */ |
+remoting.AppConnectedView.prototype.onExtensionMessage = |
+ function(type, message) { |
+ switch (type) { |
+ case 'openURL': |
+ // URL requests from the hosted app are untrusted, so disallow anything |
+ // other than HTTP or HTTPS. |
+ var url = base.getStringAttr(message, 'url'); |
+ if (url.indexOf('http:') != 0 && url.indexOf('https:') != 0) { |
+ console.error('Bad URL: ' + url); |
+ } else { |
+ window.open(url); |
+ } |
+ return true; |
+ |
+ case 'onWindowRemoved': |
+ var id = base.getNumberAttr(message, 'id'); |
+ this.windowActivationMenu_.remove(id); |
+ return true; |
+ |
+ case 'onWindowAdded': |
+ var id = base.getNumberAttr(message, 'id'); |
+ var title = base.getStringAttr(message, 'title'); |
+ this.windowActivationMenu_.add(id, title); |
+ return true; |
+ |
+ case 'onAllWindowsMinimized': |
+ chrome.app.window.current().minimize(); |
+ return true; |
+ |
+ case 'setKeyboardLayouts': |
+ var supportedLayouts = base.getArrayAttr(message, 'supportedLayouts'); |
+ var currentLayout = base.getStringAttr(message, 'currentLayout'); |
+ console.log('Current host keyboard layout: ' + currentLayout); |
+ console.log('Supported host keyboard layouts: ' + supportedLayouts); |
+ this.keyboardLayoutsMenu_.setLayouts(supportedLayouts, currentLayout); |
+ return true; |
+ |
+ case 'pingResponse': |
+ var then = base.getNumberAttr(message, 'timestamp'); |
+ var now = new Date().getTime(); |
+ this.contextMenu_.updateConnectionRTT(now - then); |
+ return true; |
+ } |
+ |
+ return false; |
+}; |
+ |
+/** |
+ * Timer callback to send the access token to the host. |
+ * @param {function(string, string)} sendExtensionMessage |
+ * @private |
+ */ |
+remoting.AppConnectedView.prototype.sendGoogleDriveAccessToken_ = |
+ function(sendExtensionMessage) { |
+ var googleDriveScopes = [ |
+ 'https://docs.google.com/feeds/', |
+ 'https://www.googleapis.com/auth/drive' |
+ ]; |
+ remoting.identity.getNewToken(googleDriveScopes).then( |
+ function(/** string */ token){ |
+ sendExtensionMessage('accessToken', token); |
+ }).catch(remoting.Error.handler(function(/** remoting.Error */ error) { |
+ console.log('Failed to refresh access token: ' + error.toString()); |
+ })); |
+}; |
+ |
})(); |