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