blob: 164a1c18042bdfd4640d13753e85bdb7fba6df6d [file] [log] [blame]
// Copyright 2014 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.
/**
* @fileoverview
* Class that routes gnubby-auth extension messages to and from the gnubbyd
* extension.
*/
'use strict';
/** @suppress {duplicate} */
var remoting = remoting || {};
/**
* @constructor
* @implements {remoting.ProtocolExtension}
*/
remoting.GnubbyAuthHandler = function() {
/** @private {?function(string,string)} */
this.sendMessageToHostCallback_ = null;
/** @private {string} */
this.gnubbyExtensionId_ = '';
/** @private {Promise} */
this.gnubbyExtensionPromise_ = null;
};
/** @private @const {string} */
remoting.GnubbyAuthHandler.EXTENSION_TYPE = 'gnubby-auth';
/** @private @const {Array<string>} */
remoting.GnubbyAuthHandler.GnubbyExtensions = [
'klnjmillfildbbimkincljmfoepfhjjj', // gNubbyd corp extension (dev)
'lkjlajklkdhaneeelolkfgbpikkgnkpk', // gNubbyd corp extension (stable)
'dlfcjilkjfhdnfiecknlnddkmmiofjbg', // gNubbyd app (dev)
'beknehfpfkghjoafdifaflglpjkojoco', // gNubbyd app (stable)
];
/**
* Determines whether any supported Gnubby extensions are installed.
*
* @return {Promise<boolean>} Promise that resolves after we have either found
* an extension or checked for the known extensions IDs without success.
* Returns true if an applicable gnubby extension was found.
*/
remoting.GnubbyAuthHandler.prototype.isGnubbyExtensionInstalled = function() {
if (this.gnubbyExtensionPromise_) {
return this.gnubbyExtensionPromise_;
}
var findGnubbyExtension = function(exts, i, resolve, reject) {
var extensionId = exts[i];
var message_callback = function(response) {
if (response) {
this.gnubbyExtensionId_ = extensionId;
console.log('Found gnubby extension: ' + extensionId);
resolve(true);
} else {
if (chrome.runtime.lastError) {
console.log('Error occurred communicating with gnubby extension: ' +
extensionId + ', error: ' +
chrome.runtime.lastError.message);
} else {
console.log('Gnubby extension "' + extensionId + '" not found');
}
if (i + 1 < exts.length) {
findGnubbyExtension.call(this, exts, i+1, resolve, reject);
} else {
// If no extensions are found, return false.
resolve(false);
}
}
}.bind(this);
chrome.runtime.sendMessage(extensionId, "HELLO", message_callback);
}
this.gnubbyExtensionPromise_ = new Promise(findGnubbyExtension.bind(
this, remoting.GnubbyAuthHandler.GnubbyExtensions, 0));
return this.gnubbyExtensionPromise_;
};
/** @override @return {Array<string>} */
remoting.GnubbyAuthHandler.prototype.getExtensionTypes = function() {
return [remoting.GnubbyAuthHandler.EXTENSION_TYPE];
};
/**
* @param {function(string,string)} sendMessageToHost Callback to send a message
* to the host.
*/
remoting.GnubbyAuthHandler.prototype.startExtension =
function(sendMessageToHost) {
this.sendMessageToHostCallback_ = sendMessageToHost;
this.sendMessageToHost_({
'type': 'control',
'option': 'auth-v1'
});
};
/**
* @param {Object} data The data to send.
* @private
*/
remoting.GnubbyAuthHandler.prototype.sendMessageToHost_ = function(data) {
this.sendMessageToHostCallback_(remoting.GnubbyAuthHandler.EXTENSION_TYPE,
JSON.stringify(data));
}
/**
* Processes gnubby-auth messages.
*
* @param {string} type The message type.
* @param {Object} message The parsed extension message data.
* @return {boolean} True if the extension message was handled.
*/
remoting.GnubbyAuthHandler.prototype.onExtensionMessage =
function(type, message) {
var messageType = base.getStringAttr(message, 'type');
if (messageType == 'data') {
this.sendMessageToGnubbyd_({
'type': 'auth-agent@openssh.com',
'data': base.getArrayAttr(message, 'data')
}, this.callback_.bind(this, base.getNumberAttr(message, 'connectionId')));
} else {
console.error('Invalid gnubby-auth message: ' + messageType);
return false;
}
return true;
};
/**
* Callback invoked with data to be returned to the host.
* @param {number} connectionId The connection id.
* @param {Object} response The JSON response with the data to send to the host.
* @private
*/
remoting.GnubbyAuthHandler.prototype.callback_ =
function(connectionId, response) {
try {
this.sendMessageToHost_({
'type': 'data',
'connectionId': connectionId,
'data': base.getArrayAttr(response, 'data')
});
} catch (/** @type {*} */ err) {
console.error('gnubby callback failed: ', err);
this.sendMessageToHost_({
'type': 'error',
'connectionId': connectionId
});
return;
}
};
/**
* Send data to the installed gnubbyd extension.
* @param {Object} jsonObject The JSON object to send to the gnubbyd extension.
* @param {function(Object)} callback The callback to invoke with reply data.
* @private
*/
remoting.GnubbyAuthHandler.prototype.sendMessageToGnubbyd_ =
function(jsonObject, callback) {
this.isGnubbyExtensionInstalled().then(
function (extensionInstalled) {
if (extensionInstalled) {
chrome.runtime.sendMessage(
this.gnubbyExtensionId_, jsonObject, callback);
}
}.bind(this)
);
};